home *** CD-ROM | disk | FTP | other *** search
/ Enter 2001 April / EnterCD4.iso / Update / SQL Server SP3 / sql70sp3i.exe / INSTALL / sp3_repl.sql < prev    next >
Encoding:
Text File  |  2000-10-04  |  115.2 KB  |  3,272 lines

  1. /*------------------------------------------------------------------------------
  2.  
  3. sp3_repl.sql
  4.  
  5. THIS SCRIPT UPDATES REPLICATION SYSTEM STORED PROCEDURES FROM 7.0 SP2 to SP3.
  6.  
  7. Changes in this file are organized as follows (please maintain):
  8.     Common system objects (replsys.sql)
  9.     Common repl objects (replcom.sql)
  10.     Tran repl objects (repltran.sql) 
  11.     Merge repl objects (rladmin.sql, rlrecon.sql, rlcore.sql)
  12.  
  13. Notes:
  14. + Catalog-updates and sp_MS_upd_sysobj_category are enabled for the entire
  15.     file.  Do not disable or re-enable them.  Please do not change set options.
  16. + grep for "--.
  17. ------------------------------------------------------------------------------*/
  18.  
  19.  
  20. --------------------------------------------------------------------------------
  21. -- VERIFY Server is started in single-user-mode (catalog-updates enabled), and
  22. --    start marking of system-objects.
  23. --------------------------------------------------------------------------------
  24. use master
  25. go
  26.  
  27. dump tran master with no_log
  28. go
  29.  
  30. exec dbo.sp_configure 'allow updates',1
  31. go
  32. reconfigure with override
  33. go
  34.  
  35. set ANSI_NULLS off
  36.  
  37. exec sp_MS_upd_sysobj_category 1
  38. go
  39.  
  40. --------------------------------------------------------------------------------
  41. --.    Common system objects (replsys.sql)
  42. --------------------------------------------------------------------------------
  43. dump tran master with no_log
  44. go
  45.  
  46. --------------------------------------------------------------------------------
  47. --.    Common repl objects (replcom.sql)
  48. --------------------------------------------------------------------------------
  49. dump tran master with no_log
  50. go
  51.  
  52. --------------------------------------------------------------------------------
  53. --.    Tran repl objects (repltran.sql) 
  54. --------------------------------------------------------------------------------
  55. dump tran master with no_log
  56. go
  57.  
  58. --------------------------------------------------------------------------------
  59. --.    Merge repl objects (rladmin.sql)
  60. --------------------------------------------------------------------------------
  61. dump tran master with no_log
  62. go
  63.        
  64. --------------------------------------------------------------------------------
  65. --.    Merge repl objects (rlcore.sql)
  66. --------------------------------------------------------------------------------
  67. dump tran master with no_log
  68. go
  69.  
  70. --------------------------------------------------------------------------------
  71. --.    Merge repl objects (rlrecon.sql)
  72. --------------------------------------------------------------------------------
  73. dump tran master with no_log
  74. go
  75.  
  76. --------------------------------------------------------------------------------
  77. --. sp_MSadd_mergereplcommand
  78. --------------------------------------------------------------------------------
  79. if exists (select * from sysobjects    where type = 'P'
  80.     and name = 'sp_MSadd_mergereplcommand')
  81.     drop procedure sp_MSadd_mergereplcommand
  82. go
  83.  
  84. raiserror('Creating procedure sp_MSadd_mergereplcommand', 0,1)
  85. GO
  86.  
  87. CREATE PROCEDURE sp_MSadd_mergereplcommand (
  88.     @publication        sysname,
  89.     @article            sysname = NULL,
  90.     @schematype            int,
  91.     @schematext            nvarchar(2000)
  92.     ) AS
  93.     declare @schemaguid            uniqueidentifier
  94.     declare @schemaversion         int
  95.     declare @retcode             int
  96.     declare @pubid                uniqueidentifier
  97.     declare @artid                uniqueidentifier
  98.     
  99.     /*
  100.     ** Publish permission check
  101.     */
  102.     exec @retcode=sp_MSreplcheck_publish
  103.     if @retcode<>0 or @@ERROR<>0 return (1)
  104.     
  105.     if @publication IS NULL
  106.         BEGIN
  107.             RAISERROR (14003, 16, -1)
  108.             RETURN (1)
  109.         END
  110.  
  111.     select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  112.     select @artid = artid FROM sysmergearticles WHERE name = @article and pubid = @pubid
  113.     /* 
  114.     ** For certain system tables that are bcped out such as MSmerge_contents 
  115.     ** and MSmerge_tombstone use the article name as sysobjects.name and get
  116.     ** sysobjects.id as the artid
  117.     */
  118.     if (@artid IS NULL) AND (@schematype <> 7)
  119.         begin
  120.             declare @binguid binary(16)
  121.             set @binguid = OBJECT_ID(@article)
  122.             set @artid = convert(uniqueidentifier, @binguid)
  123.         end
  124.  
  125.     if exists (select *    from sysmergeschemachange
  126.             where pubid = @pubid 
  127.             AND artid = @artid
  128.             AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4)) )
  129.         begin
  130.             /* Select the existing schema guid */
  131.             select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange
  132.                 where pubid = @pubid 
  133.                 AND artid = @artid
  134.                 AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4))
  135.  
  136.  
  137.             /* For directory commands, delete the previous directory before the update */
  138.             if (@schematype = 7)
  139.                 begin
  140.                     declare @dir             nvarchar(255)
  141.                     declare @local_path        nvarchar(255)
  142.                     declare @delcmd         nvarchar(255)
  143.                     declare @distributor     sysname
  144.                     declare @distproc         nvarchar(255)
  145.                     
  146.                     /*
  147.                     ** Get distribution server information for remote RPC call.
  148.                     */
  149.                     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
  150.                     IF @@ERROR <> 0 OR  @retcode <> 0
  151.                         BEGIN
  152.                             RAISERROR (14071, 16, -1)
  153.                             RETURN (1)
  154.                         END
  155.  
  156.                     select @dir = schematext from sysmergeschemachange 
  157.                         where schemaversion = @schemaversion 
  158.                     /* 
  159.                     ** We have to convert UNC to drive, otherwise will get 'Access denied' error in xp_cmdshell
  160.                     */
  161.                     EXEC @retcode = master.dbo.sp_MSunc_to_drive @unc_path = @dir, 
  162.                         @local_server = @distributor, @local_path = @local_path OUTPUT
  163.                     if @retcode<>0 or @@ERROR<>0 return (1)
  164.                     /*
  165.                     ** Delete publication directory in the distributor machine.
  166.                     */
  167.                     SET @distproc = RTRIM(@distributor) + '.master..xp_cmdshell'
  168.                     SET @delcmd = 'rmdir /S /Q "' + @local_path + '"'
  169.  
  170.                     -- Put outter quotes if running on NT
  171.                     if ((platform() & 0x1) = 0x1)
  172.                         select @delcmd = '" ' + @delcmd + ' "'  
  173.  
  174.                     EXECUTE @distproc @delcmd, NO_OUTPUT        
  175.                     if @@ERROR<>0 return (1)
  176.                 end
  177.  
  178.             /*
  179.             ** Update the schema change version
  180.             */
  181.             exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, 
  182.                 @schemaguid, @schematype, @schematext
  183.             if @@error <> 0    or @retcode <> 0
  184.                 begin
  185.                 RAISERROR(20054 , 16, -1)
  186.                 return (1)
  187.             end
  188.         end
  189.     else        
  190.         begin
  191.             /* Insert the schema change */
  192.             select @schemaversion = schemaversion from sysmergeschemachange
  193.             if (@schemaversion is NULL)
  194.                 set @schemaversion = 1
  195.             else
  196.                 select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  197.                 
  198.             /* generate a new schema guid */
  199.             set @schemaguid = newid()
  200.             exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, 
  201.                 @schemaguid, @schematype, @schematext
  202.             if @@error <> 0    or @retcode <> 0
  203.                 begin
  204.                     RAISERROR(20054 , 16, -1)
  205.                     return (1)
  206.                 end
  207.         end                
  208.         
  209.         /*
  210.         ** change last_validate column of sysmergesubscription entry that represents the publication
  211.         */
  212.         if (@schematype = 7)
  213.         begin
  214.             update sysmergesubscriptions set last_validated=getdate() where pubid=@pubid and subid=@pubid
  215.             IF @@ERROR <> 0
  216.             begin
  217.                 RAISERROR(20054 , 16, -1)
  218.                 RETURN (1)
  219.             end
  220.         end
  221.  
  222.     return (0)
  223. go
  224. exec dbo.sp_MS_marksystemobject sp_MSadd_mergereplcommand 
  225. go
  226. grant exec on dbo.sp_MSadd_mergereplcommand to public
  227. go
  228.  
  229. --------------------------------------------------------------------------------
  230. --. sp_MSdummyupdate
  231. --------------------------------------------------------------------------------
  232. if exists (select * from sysobjects    where type = 'P'
  233.     and name = 'sp_MSdummyupdate')
  234.     drop procedure sp_MSdummyupdate
  235. go
  236.  
  237. raiserror('Creating procedure sp_MSdummyupdate', 0,1)
  238. go
  239.  
  240. CREATE PROCEDURE sp_MSdummyupdate
  241.     (@rowguid uniqueidentifier, @tablenick int, @metatype tinyint, @pubid uniqueidentifier = NULL, @uplineage tinyint = 1, @inlineage varbinary(255) = NULL, @incolv varbinary(2048) = NULL)
  242. as
  243.     declare @retcode int
  244.     declare @lineage varbinary(255)
  245.     declare @mynickname int
  246.     declare @objid int
  247.     declare @col_tracking int
  248.     declare @ccols int
  249.     declare @missing_count int
  250.     declare @colv varbinary(2048)
  251.  
  252.     /*
  253.     ** Check to see if current publication has permission
  254.     */
  255.     exec @retcode=sp_MSreplcheck_connection
  256.         @tablenick = @tablenick
  257.     if @retcode<>0 or @@ERROR<>0 return (1)
  258.     
  259.     /* Parameter checks */
  260.     if (@rowguid is null)
  261.         begin
  262.         RAISERROR(14043, 16, -1, '@rowguid')
  263.         return (1)
  264.         end
  265.     if (@tablenick is null)
  266.         begin
  267.         RAISERROR(14043, 16, -1, '@tablenick')
  268.         return (1)
  269.         end
  270.     if (@metatype is null)
  271.         begin
  272.         RAISERROR(14043, 16, -1, '@metatype')
  273.         return (1)
  274.         end
  275.  
  276.     /* Check if we have a merge publication by whether system table is there */
  277.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  278.         begin
  279.         RAISERROR(20054 , 16, -1)
  280.         return (1)
  281.         end
  282.  
  283.     exec dbo.sp_MSgetreplnick @nickname = @mynickname out
  284.     if (@@error <> 0) or @mynickname IS NULL 
  285.         begin
  286.         RAISERROR (14055, 11, -1)
  287.         RETURN(1)
  288.         end                 
  289.  
  290.     if (@metatype = 0) or @@ERROR<>0
  291.         begin
  292.         declare @reason nvarchar(255)
  293.         /* We don't have the row.  Putting in a system delete tombstone should cause a delete and
  294.         ** eventual convergence.  We are already logging the row as a conflict / error.
  295.         */
  296.         set @lineage = { fn UPDATELINEAGE(0x0, @mynickname) }
  297.         select @reason = formatmessage(20562)
  298.     
  299.         insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) 
  300.             values (@rowguid, @tablenick, 6, @lineage, 0, @reason)
  301.         
  302.         end
  303.     else if (@metatype = 1)
  304.         begin
  305.         /* Update systombstone */
  306.         select @lineage = lineage from MSmerge_tombstone (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  307.             rowguid = @rowguid
  308.         if (@uplineage = 1)
  309.         begin
  310.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  311.         end
  312.         if @inlineage is not null
  313.         begin
  314.             set @lineage = @inlineage
  315.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  316.         end
  317.             
  318.         update MSmerge_tombstone set generation = 0, lineage = @lineage where
  319.             tablenick = @tablenick and rowguid = @rowguid
  320.         end
  321.     else if (@metatype = 2)
  322.         begin
  323.         /* Update MSmerge_contents */
  324.         select @lineage = lineage, @colv = colv1 from MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  325.             rowguid = @rowguid
  326.         if (@uplineage = 1)
  327.         begin
  328.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  329.             if @pubid is NULL
  330.                 select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  331.                  from sysmergearticles where nickname = @tablenick
  332.             else
  333.                 select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  334.                      from sysmergearticles where nickname = @tablenick and pubid = @pubid
  335.             if (@col_tracking = 0 or @colv is NULL)
  336.                 set @colv = NULL
  337.             else
  338.                 set @colv = { fn UPDATECOLVBM(@colv, @mynickname, 0x01, 0x00) }
  339.             
  340.         end
  341.         if @inlineage is not null
  342.         begin
  343.             set @lineage = @inlineage
  344.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  345.         end
  346.         if @incolv is not null
  347.         begin
  348.             set @colv = @incolv
  349.         end
  350.         update MSmerge_contents set generation = 0, lineage = @lineage, colv1 = @colv where
  351.             tablenick = @tablenick and rowguid = @rowguid
  352.         end
  353.     else if (@metatype = 3)
  354.         begin
  355.         set @lineage = { fn UPDATELINEAGE(0x0, @mynickname) }
  356.         -- call this again, because reconciler assumes that destination always knows about version 1 of source.
  357.         -- thus, without 2nd call, dummy update would be ignored.
  358.         set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  359.         if @pubid is NULL
  360.             select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  361.                  from sysmergearticles where nickname = @tablenick
  362.         else
  363.             select @objid = objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  364.                  from sysmergearticles where nickname = @tablenick and pubid = @pubid
  365.         if (@col_tracking = 0)
  366.             set @colv = NULL
  367.         else
  368.         begin
  369.             select @ccols= count(*) from syscolumns where id = @objid
  370.             set @ccols = @ccols + @missing_count
  371.             set @colv = { fn INITCOLVS(@ccols, @mynickname ) }
  372.         end
  373.  
  374.         if @inlineage is not null
  375.         begin
  376.             set @lineage = @inlineage
  377.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname) }
  378.         end
  379.         if @incolv is not null
  380.         begin
  381.             set @colv = @incolv
  382.         end
  383.         insert into MSmerge_contents (tablenick, rowguid, lineage, generation, colv1)
  384.             values (@tablenick, @rowguid, @lineage, 0, @colv)
  385.  
  386.         end
  387.     return (0)
  388.  
  389. go
  390. exec dbo.sp_MS_marksystemobject sp_MSdummyupdate
  391. go
  392. grant exec on dbo.sp_MSdummyupdate to public
  393. go
  394.  
  395. --------------------------------------------------------------------------------
  396. --. sp_MSenumschemachange
  397. --------------------------------------------------------------------------------
  398. if exists (select * from sysobjects    where type = 'P'
  399.     and name = 'sp_MSenumschemachange')
  400.     drop procedure sp_MSenumschemachange
  401. go
  402.  
  403. raiserror('Creating procedure sp_MSenumschemachange', 0,1)
  404. GO
  405.  
  406. CREATE PROCEDURE sp_MSenumschemachange(
  407.     @pubid             uniqueidentifier,
  408.     @schemaversion     int,
  409.     @compatibility_level int = 7000000 -- for 70 RTM and 70 SP1; SP2 and up will pass in a bigger value
  410.     )
  411. as
  412.  
  413.     /*
  414.     ** To public
  415.     */
  416.     
  417.     if (@schemaversion is null)
  418.         begin
  419.         RAISERROR(14043, 16, -1, '@schemaversion')
  420.         return (1)
  421.         end
  422.  
  423.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  424.         begin
  425.         RAISERROR(20054 , 16, -1)
  426.         return (1)
  427.         end
  428.  
  429.     /*
  430.     ** For 70 RTM and SP1, we want to filter out type 9 (retention propagation) and 16 (metadata cleanup)
  431.     ** and 5 ( last rec generation ) and 6 (last sent generation)
  432.     ** which they do not support. SP2 subscriber will be passing in 7000200, which gets all schema types
  433.     ** SP2 publishers have to offer
  434.     ** Also filter out the schematypes for the setlastsentgen (5) and setlastrecgen (6) if schemaversion > 0
  435.     ** This ensures that the subscriber does not apply these schema changes when 
  436.     ** it applies incremental schema - ie the perf optimization that is implemented 
  437.     ** by setting last sent/rec generation should be done only for brand new subscriptions.
  438.     */
  439.     select pubid, artid, schemaversion, schemaguid, schematype, schematext
  440.          from sysmergeschemachange where schemaversion > @schemaversion 
  441.              and pubid = @pubid 
  442.             and ((@compatibility_level > 7000000 and @schemaversion <= 0)
  443.             or  (@compatibility_level > 7000000 and @schemaversion > 0 and schematype not in (5, 6))
  444.             or  (schematype not in (5, 6, 9, 16)))
  445.                  order by schemaversion         
  446.     return (0)
  447. go
  448. exec dbo.sp_MS_marksystemobject sp_MSenumschemachange
  449. go
  450. grant exec on dbo.sp_MSenumschemachange to public
  451. go
  452.  
  453. --------------------------------------------------------------------------------
  454. --. sp_MSmakectsview
  455. --------------------------------------------------------------------------------
  456. if exists (select * from sysobjects    where type = 'P'
  457.     and name = 'sp_MSmakectsview')
  458.     drop procedure sp_MSmakectsview
  459. go
  460.  
  461. raiserror('Creating procedure sp_MSmakectsview', 0,1)
  462. GO
  463.  
  464. create procedure sp_MSmakectsview
  465.     @publication sysname,
  466.     @ctsview     sysname
  467. AS
  468.     set nocount on 
  469.     declare @pubid          uniqueidentifier
  470.     declare @artid          uniqueidentifier
  471.     declare @pubidstr        nvarchar(40)
  472.     declare @artidstr        nvarchar(40)
  473.     declare @objid        int
  474.     declare @tablenick    int
  475.     declare @tablenickstr nvarchar(12)
  476.     declare @command_piece nvarchar(2000)
  477.     declare @rowguidcolname sysname
  478.     declare @view_type    int
  479.     declare    @view_name  sysname
  480.     declare @or_after_first nvarchar(100)
  481.     declare @generate_per_article bit 
  482.     declare @retcode int 
  483.  
  484.     /* By default the @generate_per_article is OFF */
  485.       set @generate_per_article = 0
  486.     if @ctsview IS NULL
  487.         set @generate_per_article = 1
  488.  
  489.     set @or_after_first = ''
  490.  
  491.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  492.     exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  493.     if @@ERROR <>0 OR @retcode <> 0 
  494.         return (1)
  495.  
  496.     /* Check for the no filtering cases */
  497.     if not exists (select * from sysmergesubsetfilters where pubid = @pubid) and
  498.        not exists (select * from sysmergearticles where pubid = @pubid and
  499.                        len(subset_filterclause) > 0)
  500.            begin
  501.             if @generate_per_article = 1
  502.                 begin
  503.                     set @ctsview = 'ctsv_' + @pubidstr
  504.                     select @command_piece = N'if object_id(''' + @ctsview + ''') is NOT NULL drop view ' + @ctsview 
  505.                     exec ( @command_piece )
  506.                     if @@ERROR <>0 
  507.                         return (1)
  508.                     exec ( @command_piece )
  509.                 end
  510.             set @command_piece = 'create view ' + @ctsview + ' as select * from dbo.MSmerge_contents '
  511.  
  512.             /* Are there any published tables not in this publication? */
  513.             if exists (select * from sysmergearticles where pubid <> @pubid and
  514.                        nickname not in (select nickname from sysmergearticles where pubid = @pubid))
  515.                 begin
  516.                     /* pubidstr is needed in GUID format */
  517.                     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  518.                     set @command_piece = @command_piece + ' where tablenick in
  519.                         (select nickname from sysmergearticles where pubid = ' + @pubidstr + ')'
  520.                 end                        
  521.             if @generate_per_article = 1
  522.                 begin
  523.                     exec ( @command_piece )
  524.                     if @@ERROR <>0 
  525.                         return (1)
  526.                     select @ctsview
  527.                 end
  528.             else
  529.                 begin
  530.                     /* Now select our simple view syntax and we are done with this simple unfiltered case */
  531.                     select @command_piece
  532.                 end
  533.             return 0
  534.            end
  535.  
  536.     /* create temp table to insert into and select commands out of */
  537.     create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  538.  
  539.     if @generate_per_article = 0
  540.         begin
  541.             set @command_piece = 'create view ' + @ctsview + ' as select * from dbo.MSmerge_contents where '
  542.             insert into #tempcmd (phase, cmdtext) values (1, @command_piece)
  543.         end            
  544.  
  545.     /* Initialize for loop over articles in this publication */
  546.     select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid
  547.     while @tablenick is not null
  548.         begin
  549.         select @objid = objid, @view_type = view_type, @view_name = object_name(sync_objid) from 
  550.             sysmergearticles where pubid = @pubid and nickname = @tablenick
  551.         select @rowguidcolname = name from syscolumns where id = @objid and
  552.                 columnproperty(id, name, 'isrowguidcol')=1
  553.  
  554.         set @rowguidcolname = QUOTENAME(@rowguidcolname)
  555.         set @view_name = QUOTENAME(@view_name)
  556.         set @tablenickstr = convert(nchar(12), @tablenick)
  557.         
  558.         if @view_type <> 0
  559.             begin
  560.                 if @generate_per_article = 0
  561.                     begin
  562.                         set @command_piece = @or_after_first + ' 
  563.                         (tablenick = ' + @tablenickstr + ' and rowguid in
  564.                             (select ' + @rowguidcolname + ' from ' + @view_name + '))'
  565.                     end
  566.                 else
  567.                     begin
  568.                         select @artid = artid from sysmergearticles where nickname = @tablenick and pubid = @pubid
  569.                         set @artidstr = '''' + convert(nchar(36), @artid) + '''' 
  570.                         exec @retcode = dbo.sp_MSguidtostr @artid, @artidstr out
  571.                         if @@ERROR <>0 OR @retcode <> 0 
  572.                             return (1)
  573.                         set @ctsview = 'ctsv_' + @pubidstr + @artidstr
  574.                         select @command_piece = N'if object_id(''' + @ctsview + ''') is NOT NULL drop view ' + @ctsview 
  575.                         exec ( @command_piece )
  576.                         if @@ERROR <>0 
  577.                             return (1)
  578.  
  579.                         set @command_piece = 'create view dbo.' + @ctsview + 
  580.                             ' as select * from dbo.MSmerge_contents where (tablenick = ' + @tablenickstr + ' and rowguid in
  581.                             (select ' + @rowguidcolname + ' from ' + @view_name + ')) '
  582.                         exec ( @command_piece )
  583.                         if @@ERROR <>0 
  584.                             return (1)
  585.                     end
  586.             end                    
  587.         else
  588.             set @command_piece = @or_after_first + ' 
  589.                 (tablenick = ' + @tablenickstr + ')'
  590.  
  591.         if @generate_per_article = 0
  592.             begin
  593.                 insert into #tempcmd (phase, cmdtext) values (2, @command_piece)
  594.             end
  595.         else
  596.             begin
  597.                 insert into #tempcmd (phase, cmdtext) values (2, @ctsview)
  598.             end
  599.         
  600.         /* Advance to next article and repeat the loop */
  601.         select @tablenick = min(nickname) from sysmergearticles where
  602.             pubid = @pubid and nickname > @tablenick
  603.  
  604.         /* make it so that any subsequent selects in the view are preceded by the word OR */
  605.         set @or_after_first = ' OR '
  606.         end
  607.         
  608.     /* final steps: select out the text and drop the temp table */
  609.     if @generate_per_article = 0
  610.         begin
  611.             select cmdtext from #tempcmd order by phase, step
  612.         end            
  613.     else
  614.         /* Select the view names so that the caller can query them so they can be BCP out and dropped later */
  615.         begin
  616.             select cmdtext from #tempcmd where phase = 2 order by step 
  617.         end            
  618.  
  619.     drop table #tempcmd
  620.  
  621. go
  622. exec dbo.sp_MS_marksystemobject sp_MSmakectsview 
  623. go
  624. grant exec on dbo.sp_MSmakectsview to public
  625. go
  626.  
  627. --------------------------------------------------------------------------------
  628. --. sp_MSdrop_expired_mergesubscription
  629. --------------------------------------------------------------------------------
  630. if exists (select * from sysobjects    where type = 'P'
  631.     and name = 'sp_MSdrop_expired_mergesubscription')
  632.     drop procedure sp_MSdrop_expired_mergesubscription
  633. go
  634.  
  635. raiserror('Creating procedure sp_MSdrop_expired_mergesubscription', 0,1)
  636. GO
  637.  
  638. create procedure sp_MSdrop_expired_mergesubscription
  639. AS
  640. /*
  641. ** This stored procedure is to periodically check the status of all the subscriptions 
  642. ** of every merge publication. If any of them is out-of-date, i.e., has lost contact
  643. ** with publisher for a certain length of time, we can declare the death of that replica
  644. ** and cleanup their traces at the publisher side
  645. */
  646. declare @subscription_type  int
  647. declare @sub_type           nvarchar(5)
  648. declare @publication        sysname
  649. declare @pubid              uniqueidentifier
  650. declare @subid              uniqueidentifier
  651. declare @status             tinyint
  652. declare @publisher_id       int
  653. declare @subscriber         sysname
  654. declare @subscriber_id      int
  655. declare @subscriber_db      sysname
  656. declare @publisher_db       sysname
  657. declare @distributor        sysname
  658. declare @distribdb          sysname
  659. declare @retention          int  -- in days         
  660. declare @retcode            smallint
  661. declare @distproc           nvarchar(255)
  662. declare @localproc          nvarchar(255)
  663. declare @msg                nvarchar(255)
  664. declare @recgen             int
  665. declare @sentgen            int
  666. declare @max_distretention  int
  667. declare @recent_merge       datetime
  668. declare @minus_retention2   datetime
  669. declare @minus_retention    datetime
  670. declare @send_ts            datetime
  671. declare @receive_ts         datetime
  672.  
  673. /*
  674. ** Security Check
  675. */
  676.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  677.     IF @@ERROR <> 0 or @retcode <> 0
  678.         return (1)
  679.  
  680.  
  681.  
  682.     declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s 
  683.         where s.subid=p.pubid and s.pubid=p.pubid for read only
  684.     open PC
  685.     fetch PC into @publication, @pubid, @retention 
  686.     
  687.     WHILE (@@fetch_status <> -1)
  688.         BEGIN
  689.             /* Compute the retention period cutoff dates per publication */
  690.             select @minus_retention2 = dateadd(day, -@retention * 2, getdate())
  691.             select @minus_retention = dateadd(day, -@retention, getdate())
  692.  
  693.             if @retention is not NULL and @retention > 0
  694.             begin
  695.                     declare SC CURSOR LOCAL FAST_FORWARD for select srvid, db_name, subid, status, subscription_type from sysmergesubscriptions where 
  696.                     pubid = @pubid and pubid<>subid for read only
  697.                    open SC
  698.                 fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
  699.                 WHILE (@@fetch_status <> -1)
  700.                     BEGIN
  701.                         select @subscriber=srvname from master..sysservers where srvid=@subscriber_id
  702.                         if @subscription_type = 0 select @sub_type = 'push' else select @sub_type = 'pull'
  703.                         select @receive_ts = coldate from MSmerge_genhistory where guidsrc = (select recguid from MSmerge_replinfo 
  704.                                 where repid = @subid)
  705.                         select @sentgen=sentgen from MSmerge_replinfo where repid=@subid
  706.                         select @send_ts = coldate from MSmerge_genhistory where generation=@sentgen
  707.                         if @receive_ts>@send_ts select @recent_merge = @receive_ts
  708.                             else select @recent_merge = @send_ts
  709.                             
  710.                         if @status <> 2 and @recent_merge<@minus_retention
  711.                         begin
  712.                             exec @retcode = dbo.sp_dropmergesubscription  
  713.                                     @publication = @publication,
  714.                                     @subscriber = @subscriber,
  715.                                     @subscriber_db = @subscriber_db,
  716.                                     @subscription_type = @sub_type  
  717.                                if @retcode <>0 or @@ERROR<>0
  718.                                 goto FAILURE
  719.                         end
  720.                         if @recent_merge<@minus_retention2 
  721.                         begin
  722.                             delete from sysmergesubscriptions where subid = @subid --delete the row in sysmergesubscription
  723.                                if @@ERROR<>0
  724.                                 goto FAILURE
  725.                             delete from MSmerge_replinfo where repid = @subid
  726.                             if @@ERROR<>0
  727.                                 goto FAILURE
  728.                         end     
  729.                         fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
  730.                     END
  731.                 CLOSE SC
  732.                 DEALLOCATE SC
  733.             end
  734.             fetch PC into @publication, @pubid, @retention
  735.         END
  736.     CLOSE PC
  737.     DEALLOCATE PC
  738.     return (0)
  739.     
  740. FAILURE:
  741.     close SC
  742.     deallocate SC
  743.     close PC
  744.     deallocate PC
  745.     return (1)
  746.  
  747. GO
  748. exec dbo.sp_MS_marksystemobject sp_MSdrop_expired_mergesubscription
  749. go
  750.  
  751. --------------------------------------------------------------------------------
  752. --. sp_MScleanup_metadata
  753. --------------------------------------------------------------------------------
  754. if exists (select * from sysobjects    where type = 'P'
  755.     and name = 'sp_MScleanup_metadata')
  756.     drop procedure sp_MScleanup_metadata
  757. go
  758.  
  759. raiserror('Creating procedure sp_MScleanup_metadata', 0,1)
  760. GO
  761.  
  762. create procedure sp_MScleanup_metadata
  763. @pubid            uniqueidentifier
  764. AS
  765.  
  766.     declare @retcode                 int
  767.     declare @truncate_flag          int 
  768.     declare @artid                  uniqueidentifier
  769.     declare @rcount                    int
  770.  
  771.     /*
  772.     ** Security Check
  773.     */
  774.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  775.     IF @@ERROR <> 0 or @retcode <> 0
  776.         return (1)
  777.  
  778.     -- Figure out whether there are any publications which prevent us from truncating the tables
  779.     if @pubid is null
  780.         begin
  781.         if exists (select * from sysmergepublications where
  782.             LOWER(publisher)<> LOWER(@@SERVERNAME) or publisher_db<>db_name())
  783.             set @truncate_flag = 0
  784.         else
  785.             set @truncate_flag = 1
  786.         end
  787.     else
  788.         begin
  789.         if exists (select * from sysmergepublications p where p.pubid <> @pubid and
  790.             (LOWER(publisher)<> LOWER(@@SERVERNAME) or publisher_db<>db_name() or
  791.             not exists (select * from sysmergearticles a1, sysmergearticles a2 where
  792.                 a1.pubid = p.pubid and a2.pubid = @pubid and a1.objid = a2.objid)))
  793.             set @truncate_flag = 0
  794.         else
  795.             set @truncate_flag = 1    
  796.         end
  797.  
  798.     if @pubid is not null
  799.         begin
  800.             /* If there are any inprocess generations inform user that queisce did not     succeed - reinit required  */
  801.             if exists (select top 1 guidsrc from dbo.MSmerge_genhistory h
  802.                 where    guidlocal='00000000-0000-0000-0000-000000000000'  -- incomplete gen
  803.                     and generation not in (select gen_cur from sysmergearticles)  -- not a     local incomplete gen
  804.                     and coldate in (select login_time from master..sysprocesses)  -- not a     gen that currently receives replica updates from another db
  805.                     and h.art_nick in (select nickname from sysmergearticles where pubid = @pubid)) -- generations relevant to current publication 
  806.                 begin
  807.                     declare @dbname sysname
  808.                     set @dbname = db_name()
  809.                     RAISERROR(21504, 16, -1, @@servername, @dbname)
  810.                     return (1)
  811.                 end
  812.         end
  813.     if @truncate_flag = 1
  814.         begin
  815.         truncate table MSmerge_contents
  816.         truncate table MSmerge_tombstone
  817.         truncate table MSmerge_genhistory
  818.         update sysmergearticles set gen_cur = NULL
  819.         update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, 
  820.     sentguid = NULL 
  821.         end
  822.     else
  823.         begin
  824.         -- set up temp table of article nicknames that we delete for
  825.         create table #artnicks (nickname int)
  826.         if @pubid is null
  827.             begin
  828.             -- insert pubids for all local publications
  829.             insert into #artnicks select distinct nickname from sysmergearticles where
  830.                 pubid in (select pubid from sysmergepublications where
  831.                     LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name())
  832.             end
  833.         else
  834.             begin
  835.             insert into #artnicks select distinct nickname from sysmergearticles where
  836.                 pubid = @pubid
  837.             end
  838.         
  839.             
  840.         -- do deletions in batches of 5000 to avoid excessive log growth
  841.         
  842.         set rowcount 5000
  843.         set @rcount = 1
  844.         while @rcount > 0
  845.             begin
  846.             set @rcount = 0
  847.  
  848.             -- update our cumulative count of rows deleted in this pass with each table
  849.             delete MSmerge_contents WITH (PAGLOCK) from MSmerge_contents where tablenick in (select nickname from #artnicks)
  850.             set @rcount = @@rowcount + @rcount
  851.             delete MSmerge_tombstone WITH (PAGLOCK) from MSmerge_tombstone where tablenick in (select nickname from #artnicks)
  852.             set @rcount = @@rowcount + @rcount
  853.             delete MSmerge_genhistory WITH (PAGLOCK) from MSmerge_genhistory where art_nick in (select nickname from #artnicks)
  854.             set @rcount = @@rowcount + @rcount
  855.             end
  856.         
  857.         update sysmergearticles set gen_cur = NULL where nickname in (select nickname from #artnicks)
  858.  
  859.         if @pubid is not null
  860.             update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  861.                 where repid in ( select subid from sysmergesubscriptions where pubid = @pubid)
  862.         else
  863.             update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  864.                 where repid in ( select subid from sysmergesubscriptions s, sysmergepublications p
  865.                     where s.pubid = p.pubid and LOWER(p.publisher)=LOWER(@@SERVERNAME) and p.publisher_db=db_name())
  866.         
  867.         drop table #artnicks
  868.         dbcc dbreindex ( MSmerge_contents )
  869.         end
  870.  
  871.     execute @retcode = dbo.sp_MSmakegeneration 
  872.     if @@ERROR <> 0 or @retcode <> 0
  873.         return (1)
  874.     return 0
  875.     
  876. GO
  877. exec dbo.sp_MS_marksystemobject sp_MScleanup_metadata
  878. go
  879. grant execute on dbo.sp_MScleanup_metadata to public
  880. go
  881.  
  882.  
  883. --------------------------------------------------------------------------------
  884. --. sp_mergecleanupmetadata
  885. --------------------------------------------------------------------------------
  886. if exists (select * from sysobjects    where type = 'P'
  887.     and name = 'sp_mergecleanupmetadata')
  888.     drop procedure sp_mergecleanupmetadata
  889. go
  890.  
  891. raiserror('Creating procedure sp_mergecleanupmetadata', 0,1)
  892. GO
  893.  
  894. create procedure sp_mergecleanupmetadata
  895.     @publication                sysname = '%',
  896.     @reinitialize_subscriber    nvarchar(5) = 'true'
  897. AS
  898. declare @pubid            uniqueidentifier
  899. declare @retcode        int
  900. declare @pubname          sysname
  901. declare @snapshot_ready int
  902.  
  903. declare @artid                  uniqueidentifier
  904. declare @schematype             int
  905. declare @schemaversion          int
  906. declare @schemaguid             uniqueidentifier
  907. declare @schematext             nvarchar(2000)
  908. declare @make_generation         int
  909.  
  910. set @make_generation = 0
  911.  
  912. /*
  913. ** Security Check
  914. */
  915. EXEC @retcode = dbo.sp_MSreplcheck_publish
  916. IF @@ERROR <> 0 or @retcode <> 0
  917.     return (1)
  918.  
  919. if not exists (select * from sysobjects where name='sysmergearticles')
  920.     return (1)
  921.     
  922. begin TRAN
  923. declare #per_publication CURSOR LOCAL FAST_FORWARD for select pubid
  924.     from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and name like @publication
  925. open #per_publication
  926. fetch #per_publication into @pubid
  927. while @@fetch_status<>-1
  928. begin
  929.     select @pubname=name, @snapshot_ready=snapshot_ready from sysmergepublications where pubid=@pubid
  930.     if @publication <> '%' and exists (select * from sysmergearticles where pubid<>@pubid and objid in
  931.         (select objid from sysmergearticles where pubid=@pubid))
  932.     begin
  933.         raiserror(21287, 16, -1, @pubname)
  934.         goto FAILURE
  935.     end
  936.  
  937.     /* Only do this when snapshot has been ran before this operation */
  938.     if @snapshot_ready>0
  939.     begin
  940.         if LOWER(@reinitialize_subscriber)='true'
  941.         begin
  942.             exec @retcode = sp_reinitmergesubscription @publication=@pubname
  943.             if @@ERROR<>0 or @retcode<>0
  944.             begin
  945.                 close #per_publication
  946.                 deallocate #per_publication
  947.                 goto FAILURE
  948.             end
  949.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  950.             if @@ERROR<>0
  951.             begin
  952.                 close #per_publication
  953.                 deallocate #per_publication
  954.                 goto FAILURE
  955.             end
  956.         end
  957.         else
  958.         begin
  959.             select @schemaversion = schemaversion from sysmergeschemachange
  960.             if (@schemaversion is NULL)
  961.             set @schemaversion = 1
  962.             else
  963.                 select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  964.             set @schemaguid = newid()
  965.             set @artid = newid()
  966.             set @schematype = 16 /* metadata cleanup */
  967.             select @schematext = 'exec dbo.sp_MScleanup_metadata '+ '''' + convert(nchar(36),@pubid) + '''' 
  968.             exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  969.             if @@ERROR<>0 or @retcode<>0 
  970.             begin
  971.                 close #per_publication
  972.                 deallocate #per_publication
  973.                 goto FAILURE            
  974.             end
  975.         end
  976.     end
  977.     
  978.     set @make_generation = 1
  979.     fetch next from #per_publication into @pubid
  980. end
  981. close #per_publication
  982. deallocate #per_publication
  983. COMMIT TRAN
  984.  
  985. if @publication = '%'
  986.     begin
  987.         set @pubid = NULL
  988.     end
  989. else
  990.     begin
  991.         select @pubid = pubid from sysmergepublications 
  992.             where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and name = @publication
  993.     end
  994.  
  995. exec @retcode = dbo.sp_MScleanup_metadata @pubid
  996. if @@ERROR <> 0 or @retcode <> 0
  997.         goto FAILURE
  998.  
  999. if @make_generation = 1
  1000.     begin
  1001.         execute @retcode = dbo.sp_MSmakegeneration 
  1002.         if @@ERROR <> 0 or @retcode <> 0
  1003.                goto FAILURE
  1004.     end
  1005. return (0)
  1006. FAILURE:
  1007. if @@TRANCOUNT = 1 
  1008.     ROLLBACK TRANSACTION 
  1009. else
  1010.     COMMIT TRANSACTION 
  1011. return (1)
  1012.  
  1013. GO
  1014. exec dbo.sp_MS_marksystemobject sp_mergecleanupmetadata
  1015. go
  1016. grant execute on dbo.sp_mergecleanupmetadata to public
  1017. go
  1018.  
  1019. --------------------------------------------------------------------------------
  1020. --. sp_enumcustomresolvers
  1021. --------------------------------------------------------------------------------
  1022. if exists (select * from sysobjects    where type = 'P'
  1023.     and name = 'sp_enumcustomresolvers')
  1024.     drop procedure sp_enumcustomresolvers
  1025. go
  1026.  
  1027. raiserror('Creating procedure sp_enumcustomresolvers', 0,1)
  1028. GO
  1029.  
  1030. CREATE PROCEDURE sp_enumcustomresolvers
  1031. --    @distributor parameter will be removed in the next version.   
  1032.     @distributor     sysname = NULL
  1033.     AS
  1034.     SET NOCOUNT ON
  1035.  
  1036.     declare @distributor_rpc sysname
  1037.     declare @return_status int
  1038.     declare @distproc nvarchar(100)
  1039.     declare @retcode int
  1040.  
  1041.     select @return_status = 0
  1042.  
  1043.     /*
  1044.     ** Get the distributor 
  1045.     */
  1046.     EXEC @return_status = dbo.sp_helpdistributor @rpcsrvname = @distributor_rpc OUTPUT
  1047.     IF @@error <> 0 OR @return_status <> 0 OR @distributor_rpc IS NULL
  1048.     BEGIN
  1049.         RAISERROR (20036, 16, -1)
  1050.         RETURN (1)
  1051.     END
  1052.  
  1053.    
  1054.     /*
  1055.     ** For a local distributor, query the registry directly
  1056.     */
  1057.     if @distributor_rpc = @@servername 
  1058.        begin
  1059.         declare @key_exists int
  1060.         select @key_exists = 0
  1061.         create table #keyexists (keyexists int) 
  1062.         select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regread'
  1063.         insert into #keyexists exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver'
  1064.         select @key_exists = keyexists from #keyexists
  1065.         if (@key_exists = 1)
  1066.             begin
  1067.                 select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regenumvalues'
  1068.                 exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver'    
  1069.                 if @@ERROR<>0 return (1)
  1070.             end
  1071.         drop table #keyexists
  1072.     end
  1073.     /* 
  1074.     ** Since a downlevel publisher can connect to a remote distributor with a higher
  1075.     ** version, it is better to return the resolver list using the RPC as opposed
  1076.     ** to reading regkeys directly since they might change from version to version.
  1077.     */
  1078.     else
  1079.     begin
  1080.         
  1081.         select @distproc = RTRIM(@distributor_rpc) + '.master..sp_enumcustomresolvers'
  1082.         exec @distproc 
  1083.         if @@ERROR<> 0 
  1084.             return (1)
  1085.     end
  1086.     RETURN (0)
  1087.  
  1088. GO
  1089. exec dbo.sp_MS_marksystemobject sp_enumcustomresolvers
  1090. go
  1091.  
  1092. grant execute on dbo.sp_enumcustomresolvers to public
  1093. go
  1094.  
  1095. --------------------------------------------------------------------------------
  1096. --. sp_MSexpandsubsnb
  1097. --------------------------------------------------------------------------------
  1098. if exists (select * from sysobjects    where type = 'P'
  1099.     and name = 'sp_MSexpandsubsnb')
  1100.     drop procedure sp_MSexpandsubsnb
  1101. go
  1102.  
  1103. raiserror('Creating procedure sp_MSexpandsubsnb', 0,1)
  1104. GO
  1105.  
  1106. create PROCEDURE sp_MSexpandsubsnb (@pubid uniqueidentifier)
  1107. AS
  1108.     declare @filterid int
  1109.     declare @base_nick int
  1110.     declare @join_nick int
  1111.     declare @basetable nvarchar(258)
  1112.     declare @jointable nvarchar(258)
  1113.     declare @join_clause nvarchar(4000)
  1114.     declare @retcode int
  1115.     declare @base_nickstr nvarchar(10)
  1116.     declare @join_unique_key int
  1117.  
  1118.     /* get first filter to expand on */
  1119.     select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
  1120.         where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag
  1121.  
  1122.     while @filterid is not null
  1123.         begin
  1124.         /* get join clause and tables for this filter */
  1125.         select @join_nick = join_nickname, @join_clause = join_filterclause,
  1126.             @base_nick = art_nickname, @join_unique_key = join_unique_key from sysmergesubsetfilters where
  1127.                 pubid = @pubid and join_filterid = @filterid
  1128.         exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @jointable out, @pubid
  1129.         exec @retcode = dbo.sp_MStablenamefromnick @base_nick, @basetable out, @pubid
  1130.         set @base_nickstr = convert(nchar(10), @base_nick)
  1131.  
  1132.         /* Mark rows so that we know we've expanded those rows for this filter */
  1133.         update #notbelong set flag = @filterid where flag < @filterid
  1134.         
  1135.         /* exec an insert/select query to expand #notbelong */
  1136.         exec ('insert into #notbelong (tablenick, rowguid, flag) select ' +
  1137.                 @base_nickstr + ', ' + @basetable + '.RowGuidCol, 0 from ' + @basetable + 
  1138.                 ', ' + @jointable + ' where ( ' + @jointable + '.RowGuidCol in 
  1139.                     (select rowguid from #notbelong) ) and (' + @join_clause + ')')
  1140.                     
  1141.         /* 
  1142.         ** if any rows inserted, try to contract the #notbelong table.
  1143.         ** Only join filters that are non unique need to contract the 
  1144.         ** NOTBELONGS table - 
  1145.         */
  1146.         if @@rowcount <> 0 and @join_unique_key = 0
  1147.             exec @retcode = dbo.sp_MScontractsubsnb @pubid, @base_nick, @basetable
  1148.         
  1149.         /* get next filter to expand with */
  1150.         select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
  1151.             where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag
  1152.         end
  1153. go
  1154.  
  1155. exec dbo.sp_MS_marksystemobject sp_MSexpandsubsnb 
  1156. go
  1157. grant exec on dbo.sp_MSexpandsubsnb to public
  1158. go
  1159.  
  1160. --------------------------------------------------------------------------------
  1161. --. sp_addmergearticle
  1162. --------------------------------------------------------------------------------
  1163. if exists (select * from sysobjects    where type = 'P'
  1164.     and name = 'sp_addmergearticle')
  1165.     drop procedure sp_addmergearticle
  1166. go
  1167.  
  1168. raiserror('Creating procedure sp_addmergearticle', 0,1)
  1169. GO
  1170.  
  1171. create procedure sp_addmergearticle
  1172.     @publication            sysname,                            /* publication name */
  1173.     @article                sysname,                            /* article name */
  1174.     @source_object          sysname,                            /* source object name */
  1175.     @type                   sysname = 'table',                  /* article type */
  1176.     @description            nvarchar(255)= NULL,                /* article description */
  1177.     @column_tracking        nvarchar(10) = 'false',             /* column level tracking */
  1178.     @status                 nvarchar(10) = 'unsynced',          /* unsynced, active */
  1179.     @pre_creation_cmd       nvarchar(10) = 'drop',              /* 'none', 'drop', 'delete', 'truncate' */
  1180.     @creation_script        nvarchar(255)= NULL,                /* article schema script */
  1181.     @schema_option          binary(8)   = 0x00000000000000f1,   /* article schema creation options */
  1182.     @subset_filterclause    nvarchar(2000) = '',                /* filter clause */
  1183.     @article_resolver       nvarchar(255)= NULL,                 /* custom resolver for article */
  1184.     @resolver_info          nvarchar(255) = NULL,                     /* custom resolver info */
  1185.     @source_owner           sysname = NULL
  1186.     AS
  1187.  
  1188.     set nocount on
  1189.  
  1190.     /*
  1191.     ** Declarations.
  1192.     */
  1193.     declare @resolver_info_len        int
  1194.     declare @sp_resolver            sysname
  1195.     declare @num_columns            smallint
  1196.     declare @pubid                  uniqueidentifier                /* Publication id */
  1197.     declare @db                     sysname
  1198.     declare @object                 sysname
  1199.     declare @owner                  sysname
  1200.     declare @destination_object     sysname
  1201.     declare @retcode                int
  1202.     declare @objid                  int
  1203.     declare @sync_objid             int
  1204.     declare @typeid                 smallint
  1205.     declare @nickname               int
  1206.     declare @merge_pub_object_bit int
  1207.     declare @column_tracking_id     int
  1208.     declare @cmd                    nvarchar(255)
  1209.     declare @statusid               tinyint
  1210.     declare @precmdid               int
  1211.     declare @resolver_clsid         nvarchar(50)
  1212.     declare @resolver_clsid_old     nvarchar(50)
  1213.     declare @tablenick              int
  1214.     declare @artid                  uniqueidentifier
  1215.     declare @distributor            sysname
  1216.     declare @distribdb              sysname
  1217.     declare @distproc               nvarchar(255)
  1218.     declare @dbname                 sysname
  1219.     declare @replinfo               int
  1220.     declare @db_name                sysname
  1221.     declare @subset                 int
  1222.     declare @row_size               int
  1223.     declare @sp_name                sysname
  1224.     declare @sp_owner                sysname
  1225.     declare @qualified_name         nvarchar(257)
  1226.  
  1227.     -- PARSENAME VARS
  1228.     declare     @UnqualName      nvarchar(258)  --rightmost name node
  1229.                ,@QualName1       nvarchar(258)  
  1230.                ,@QualName2       nvarchar(258)
  1231.     -- END PARSENAME VARS
  1232.  
  1233.     /*
  1234.     ** Initializations 
  1235.     */
  1236.     select @statusid        = 0
  1237.     select @resolver_clsid  = NULL
  1238.     select @subset          = 1     /* Const: publication type 'subset' */
  1239.     select @merge_pub_object_bit    = 128
  1240.  
  1241.     select @sp_resolver = 'Microsoft SQLServer Stored Procedure Resolver'
  1242.     
  1243.     if @source_owner is NULL
  1244.         begin
  1245.             select @source_owner = user_name(uid) from sysobjects where id = object_id(@source_object)
  1246.             if @source_owner is NULL  
  1247.                 begin
  1248.                     raiserror (14027, 11, -1, @source_object)
  1249.                     return (1)
  1250.                 end
  1251.         end
  1252.     select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object)
  1253.     
  1254.     /*
  1255.     ** Security Check
  1256.     */
  1257.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  1258.     IF @@ERROR <> 0 or @retcode <> 0
  1259.         return (1)
  1260.  
  1261.     /*
  1262.     ** Parameter Check: @publication.
  1263.     ** The @publication id cannot be NULL and must conform to the rules
  1264.     ** for identifiers.
  1265.     */   
  1266.         
  1267.     if @publication is NULL
  1268.         begin
  1269.             raiserror (14043, 16, -1, '@publication')
  1270.             return (1)
  1271.         end
  1272.  
  1273.     select @pubid = pubid from sysmergepublications 
  1274.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  1275.     if @pubid is NULL
  1276.         begin
  1277.             raiserror (14027, 11, -1, @publication)
  1278.             return (1)
  1279.         end
  1280.     /*
  1281.     ** Only publisher can call sp_addmergearticle
  1282.     */
  1283.     EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  1284.     IF @@ERROR <> 0 or @retcode <>  0
  1285.         BEGIN
  1286.             RAISERROR (20073, 16, -1)
  1287.             RETURN (1)
  1288.         END
  1289.         
  1290.     select @sync_objid = id from sysobjects where id = OBJECT_ID(@qualified_name)
  1291.     if @sync_objid is NULL
  1292.         begin
  1293.             raiserror (14027, 11, -1, @qualified_name)
  1294.             return (1)
  1295.         end
  1296.  
  1297.     select @row_size=sum(length) from syscolumns where id=OBJECT_ID(@qualified_name)
  1298.     if @row_size>6000 
  1299.         begin
  1300.             RAISERROR (21062, 16, -1, @qualified_name)  
  1301.             -- RETURN (1)
  1302.         end
  1303.  
  1304.     select @num_columns=count(*) from syscolumns where id = object_id(@qualified_name)
  1305.     if @num_columns > 246
  1306.         begin
  1307.             RAISERROR (20068, 16, -1, @qualified_name, 246)
  1308.             RETURN (1)
  1309.         end
  1310.  
  1311.     /*
  1312.     ** Parameter Check: @article.
  1313.     ** Check to see that the @article is local, that it conforms
  1314.     ** to the rules for identifiers, and that it is a table, and not
  1315.     ** a view or another database object.
  1316.     */
  1317.  
  1318.     if @article is NULL
  1319.         begin
  1320.             raiserror (20045, 16, -1)
  1321.             return (1)
  1322.         end
  1323.  
  1324.     exec @retcode = dbo.sp_MSreplcheck_name @article
  1325.     if @@ERROR <> 0 or @retcode <> 0
  1326.         return(1)
  1327.         
  1328.     /*
  1329.     ** Merge does not really support destination object. It has the same value as source
  1330.     */
  1331.     select @destination_object = @source_object
  1332.  
  1333.     /*
  1334.     **  Get the id of the @qualified_name
  1335.     */
  1336.     select @objid = id, @replinfo = replinfo from sysobjects where id = OBJECT_ID(@qualified_name)
  1337.     if @objid is NULL
  1338.         begin
  1339.             raiserror (14027, 11, -1, @qualified_name)
  1340.             return (1)
  1341.         end
  1342.  
  1343.     /*
  1344.     ** If current publication contains a non-sync subscription, all articles to be added in it
  1345.     ** has to contain a rowguidcol.
  1346.     */
  1347.     if exists (select * from sysmergesubscriptions where pubid = @pubid and sync_type = 2)
  1348.         begin
  1349.             if not exists (select * from syscolumns c 
  1350.                 where c.id=@objid and ColumnProperty(c.id, c.name, 'isrowguidcol') = 1)
  1351.                 begin
  1352.                     raiserror(20085 , 16, -1, @article, @publication)
  1353.                     return (1)
  1354.                 end
  1355.         end
  1356.  
  1357.     /*
  1358.     ** Make sure that the table name specified is a table and not a view.
  1359.     */
  1360.  
  1361.     if NOT exists (select * from sysobjects
  1362.         where id = (select OBJECT_ID(@qualified_name)) AND type = 'U')
  1363.         begin
  1364.             raiserror (20074, 16, -1)
  1365.             return (1)
  1366.         end
  1367.  
  1368.     /*
  1369.     ** Check that the underlying table has no timestamp columns.  If it does,
  1370.     ** return an appropriate error.
  1371.     */
  1372.     
  1373.     if EXISTS (SELECT * FROM syscolumns c WHERE c.id = @sync_objid
  1374.                 AND type_name(c.xtype) = 'timestamp')
  1375.         BEGIN
  1376.             RAISERROR (20055, 16, -1, @qualified_name)
  1377.             RETURN (1)
  1378.         END
  1379.         
  1380.     /*
  1381.     ** Parameter Check:  @creation_script and @schema_option
  1382.     ** @schema_option cannot be null
  1383.     ** If @schema_option is 0, there have to be @creation_script defined.
  1384.     */
  1385.     IF @schema_option IS NULL
  1386.     BEGIN
  1387.         select @schema_option  = 0x00000000000000f1
  1388.     END
  1389.  
  1390.     IF @schema_option = 0x0000000000000000
  1391.     BEGIN
  1392.         RAISERROR (3217, 16, -1, '@schema_option')
  1393.         RETURN (1)
  1394.     END
  1395.  
  1396.     /*
  1397.     ** Set the typeid.  The default type is table.  Anything else is
  1398.     ** currently undefined (reserved for future use).
  1399.     **
  1400.     **      @typeid     type
  1401.     **      =======     ========
  1402.     **          1       table
  1403.     ** UNDONE - message
  1404.     */
  1405.  
  1406.     IF LOWER(@type) NOT IN ('table')
  1407.        BEGIN
  1408.             RAISERROR (20074, 16, -1)
  1409.             RETURN (1)
  1410.        END
  1411.  
  1412.     IF LOWER(@type) = 'table'
  1413.        SET @typeid = 0x0a
  1414.  
  1415.     /*
  1416.     ** Validate the column tracking
  1417.     */
  1418.     if @column_tracking IS NULL OR LOWER(@column_tracking) NOT IN ('true', 'false')
  1419.         BEGIN
  1420.             RAISERROR (14148, 16, -1, '@column_tracking')
  1421.             RETURN (1)
  1422.         END
  1423.     if LOWER(@column_tracking) = 'true' 
  1424.         SET @column_tracking_id = 1
  1425.     else 
  1426.         SET @column_tracking_id = 0
  1427.  
  1428.     /*
  1429.     ** Get the pubid.
  1430.     */
  1431.     SELECT @pubid = pubid FROM sysmergepublications 
  1432.         WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  1433.     if @pubid is NULL
  1434.         begin
  1435.             raiserror (14027, 11, -1, @publication)
  1436.             return (1)
  1437.         end
  1438.  
  1439.     /*
  1440.     ** Parameter Check:  @article, @publication.
  1441.     ** Check if the article already exists in this publication.
  1442.     */
  1443.  
  1444.     IF EXISTS (SELECT *
  1445.                  FROM sysmergearticles
  1446.                 WHERE pubid = @pubid
  1447.                   AND name = @article)
  1448.         BEGIN
  1449.             RAISERROR (14030, 16, -1, @article, @publication)
  1450.             RETURN (1)
  1451.         END
  1452.         
  1453.     execute @retcode = dbo.sp_MSgetreplnick @pubid = @pubid, @nickname = @nickname output
  1454.     if (@@error <> 0) or @retcode <> 0 or @nickname IS NULL 
  1455.         begin
  1456.         RAISERROR (14055, 11, -1)
  1457.         RETURN(1)
  1458.         end                 
  1459.  
  1460.     /*
  1461.     ** Set the precmdid.  The default type is 'drop'.
  1462.     **
  1463.     **      @precmdid   pre_creation_cmd
  1464.     **      =========   ================
  1465.     **            0     none
  1466.     **          1     drop
  1467.     **          2     delete
  1468.     **          3     truncate
  1469.     */
  1470.     IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop', 'delete', 'truncate')
  1471.        BEGIN
  1472.           RAISERROR (14061, 16, -1)
  1473.           RETURN (1)
  1474.        END
  1475.  
  1476.     /*
  1477.     ** Determine the integer value for the pre_creation_cmd.
  1478.     */
  1479.     IF LOWER(@pre_creation_cmd) = 'none'
  1480.        select @precmdid = 0
  1481.     ELSE IF LOWER(@pre_creation_cmd) = 'drop'
  1482.        select @precmdid = 1
  1483.     ELSE IF LOWER(@pre_creation_cmd) = 'delete'
  1484.        select @precmdid = 2
  1485.     ELSE IF LOWER(@pre_creation_cmd) = 'truncate'
  1486.        select @precmdid = 3
  1487.  
  1488.     /*
  1489.     ** Validate the article resolver
  1490.     */
  1491.     if @article_resolver IS NOT NULL
  1492.         begin
  1493.             if @article_resolver = 'default' OR @article_resolver = ''
  1494.                 begin
  1495.                     select @article_resolver = NULL
  1496.                     select @resolver_clsid = NULL
  1497.                 end                 
  1498.             else
  1499.                 begin
  1500.                     /*
  1501.                     ** Get the distributor info
  1502.                     */
  1503.                     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
  1504.                     IF @@error <> 0 OR @retcode <> 0 OR @distributor IS NULL
  1505.                         BEGIN
  1506.                             RAISERROR (20036, 16, -1)
  1507.                             RETURN (1)
  1508.                     END
  1509.                     select @distproc = RTRIM(@distributor) + '.master.dbo.xp_regread'
  1510.                     EXECUTE @retcode = @distproc 'HKEY_LOCAL_MACHINE',
  1511.                                   'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver',
  1512.                                   @article_resolver,
  1513.                                   @param = @resolver_clsid  OUTPUT
  1514.  
  1515.                     /* if xp_regread failed, is it because distributor server is running on Shiloh */
  1516.                     IF @retcode <> 0 or @resolver_clsid IS NULL
  1517.                         begin
  1518.                             EXECUTE @retcode = @distproc 'HKEY_LOCAL_MACHINE',
  1519.                                 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver',
  1520.                                 @article_resolver,
  1521.                                 @param = @resolver_clsid  OUTPUT
  1522.                             IF @retcode <> 0 or @resolver_clsid IS NULL
  1523.                                 BEGIN
  1524.                                     select @distproc =  RTRIM(@distributor) + '.master.dbo.sp_MSread_resolver_clsid'
  1525.                                     exec @retcode=@distproc @article_resolver,@param = @resolver_clsid OUTPUT
  1526.                                     if @retcode<>0 or @@ERROR<>0 or @resolver_clsid is NULL
  1527.                                         begin
  1528.                                               RAISERROR (20020, 16, -1)
  1529.                                               RETURN (1)
  1530.                                           end
  1531.                                 END
  1532.                         end
  1533.                 end
  1534.         end
  1535.  
  1536.         /*
  1537.         ** If article resolver is 'SP resolver', make sure that resolver_info refers to an SP or XP;
  1538.         ** Also make sure it is stored with owner qualification
  1539.         */
  1540.         if  @article_resolver = @sp_resolver
  1541.             begin
  1542.                 if not exists (select * from sysobjects where id = object_id(@resolver_info) and ( type = 'P' or type = 'X'))
  1543.                     begin
  1544.                         select @resolver_info_len = datalength(@resolver_info)
  1545.                         raiserror(2812, 16, -1, @resolver_info_len, @resolver_info)
  1546.                         return (1)
  1547.                     end
  1548.                     
  1549.                 select @sp_name = name, @sp_owner=user_name(uid) from sysobjects where id = object_id(@resolver_info)
  1550.                 select @resolver_info = QUOTENAME(@sp_owner) + '.' + QUOTENAME(@sp_name) 
  1551.             end
  1552.     /*
  1553.     ** Validate the resolver procedure for the article - should be either a stored proc or an extended procedure.
  1554.     */
  1555.     if @resolver_info IS NOT NULL
  1556.         begin
  1557.             /*
  1558.             ** Get the distributor info
  1559.             */
  1560.             EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
  1561.             IF @@error <> 0 OR @retcode <> 0 OR @distributor IS NULL
  1562.                 BEGIN
  1563.                     RAISERROR (20036, 16, -1)
  1564.                     RETURN (1)
  1565.             END
  1566.             select @distproc = RTRIM(@distributor) + '.master.dbo.xp_regread'
  1567.             /* Don't force different resolver than one that was passed in. */
  1568.         end             
  1569.  
  1570.  
  1571.     /*
  1572.     **  Add article to sysmergearticles and update sysobjects category bit.
  1573.     */
  1574.     begin tran
  1575.     save TRAN sp_addmergearticle
  1576.         select @artid = artid from sysmergearticles where objid = OBJECT_ID(@qualified_name)
  1577.         select @statusid = 1  /*default status is inactive */
  1578.         if @artid is NULL
  1579.             begin
  1580.                 set @artid = newid()
  1581.                 if @@ERROR <> 0
  1582.                     goto FAILURE
  1583.                 execute @retcode = dbo.sp_MSgentablenickname @tablenick output, @nickname, @objid
  1584.                 if @@ERROR <> 0 OR @retcode <> 0
  1585.                     goto FAILURE
  1586.             end
  1587.         /* Clone the article properties if article has already been published (in a different pub) */
  1588.         else
  1589.             begin
  1590.             /*
  1591.             ** Parameter Check:  @article, @publication.
  1592.             ** Check if the table already exists in this publication.
  1593.             */
  1594.             if exists (select * from sysmergearticles
  1595.                 where pubid = @pubid AND artid = @artid)
  1596.                 begin
  1597.                     raiserror (14030, 16, -1, @article, @publication)
  1598.                     goto FAILURE
  1599.                 end
  1600.             
  1601.             /* Make sure that coltracking option matches */
  1602.             if exists (select * from sysmergearticles where artid = @artid and
  1603.                          column_tracking <> @column_tracking_id)
  1604.                 begin
  1605.                     raiserror (20030, 16, -1, @article)
  1606.                     goto FAILURE
  1607.                 end
  1608.  
  1609.             /* Reuse the article nickname if article has already been published (in a different pub)*/
  1610.             select @tablenick = nickname from sysmergearticles where artid = @artid
  1611.             if @tablenick IS NULL
  1612.                 goto FAILURE
  1613.                 
  1614.             /* Make sure that @resolver_clsid matches the existing resolver_clsid */
  1615.             select @resolver_clsid_old = resolver_clsid from sysmergearticles where artid = @artid 
  1616.             if ((@resolver_clsid IS NULL AND @resolver_clsid_old IS NOT NULL) OR
  1617.                 (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NULL) OR
  1618.                 (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NOT NULL AND @resolver_clsid_old <> @resolver_clsid))
  1619.                 begin
  1620.                     raiserror (20037, 16, -1, @article)
  1621.                     goto FAILURE
  1622.                 end
  1623.  
  1624.             /* Insert to articles, copying some stuff from other article row */
  1625.             set rowcount 1
  1626.             insert into sysmergearticles (name, type, objid, sync_objid, artid, description,
  1627.                     pre_creation_command, pubid, nickname, column_tracking, status,
  1628.                     conflict_table, creation_script, conflict_script, article_resolver,
  1629.                     resolver_clsid, ins_conflict_proc, schema_option, 
  1630.                     destination_object, subset_filterclause, view_type, resolver_info, gen_cur)
  1631.                 -- use top 1, distinct could return more than one matching row if status different on partitioned articles
  1632.                 select top 1 @article, type, objid, @sync_objid, @artid, @description, @precmdid,
  1633.                     @pubid, nickname, column_tracking, 1, conflict_table, @creation_script,
  1634.                     conflict_script, article_resolver, resolver_clsid, ins_conflict_proc,
  1635.                     @schema_option, @destination_object, @subset_filterclause, 0, resolver_info, gen_cur
  1636.                     from sysmergearticles where artid = @artid
  1637.             set rowcount 0
  1638.  
  1639.             /* Jump to end of transaction  */
  1640.             goto DONE_TRAN
  1641.             end
  1642.  
  1643.         /* Add the specific GUID based replication columns to sys articles */
  1644.         insert sysmergearticles (name, objid, sync_objid, artid, type, description, pubid, nickname, 
  1645.                 column_tracking, status, schema_option, pre_creation_command, destination_object, 
  1646.                 article_resolver, resolver_clsid, subset_filterclause, view_type, resolver_info)
  1647.         values (@article, @objid, @sync_objid, @artid, @typeid, @description, @pubid, @tablenick, 
  1648.                 @column_tracking_id, @statusid, @schema_option, @precmdid, @destination_object, 
  1649.                 @article_resolver, @resolver_clsid, @subset_filterclause, 0, @resolver_info)
  1650.         if @@ERROR <> 0
  1651.             goto FAILURE
  1652.  
  1653.         exec @retcode = dbo.sp_replupdateschema @qualified_name
  1654.         if @@ERROR <> 0 or @retcode <> 0
  1655.             goto FAILURE
  1656.         update sysobjects set replinfo = (replinfo | @merge_pub_object_bit) where id = @objid
  1657.         if @@ERROR <> 0
  1658.             goto FAILURE
  1659.         /* Make a generation */
  1660.         execute @retcode = dbo.sp_MSmakegeneration 
  1661.         if @@ERROR <> 0 
  1662.             goto FAILURE
  1663.  
  1664.                 /* If the article status is active then publish the user tables */
  1665.         if @status = 'active'
  1666.             begin
  1667.                 /* Get a holdlock on the underlying table */
  1668.                 select @cmd = 'select * into #tab1 from '
  1669.                 select @cmd = @cmd + @qualified_name 
  1670.                 select @cmd = @cmd + '(TABLOCK HOLDLOCK) where 1 = 2 '
  1671.                 execute(@cmd)
  1672.  
  1673.                 /* Add the guid column to the user table */
  1674.                 execute @retcode = dbo.sp_MSaddguidcolumn @source_owner, @source_object
  1675.                 if @@ERROR <> 0 OR  @retcode <> 0  -- NOTE: new change
  1676.                     goto FAILURE
  1677.  
  1678.                 /* Create an index on the rowguid column in the user table */
  1679.                 execute @retcode = dbo.sp_MSaddguidindex @source_owner, @source_object
  1680.                 if @@ERROR <> 0 OR @retcode <> 0
  1681.                     goto FAILURE
  1682.  
  1683.                 /* Create the merge triggers on the base table */
  1684.                 execute @retcode = dbo.sp_MSaddmergetriggers @qualified_name, @column_tracking_id
  1685.                 if @@ERROR <> 0 OR @retcode <> 0
  1686.                     goto FAILURE 
  1687.  
  1688.                 /* Create the merge insert/update stored procedures for the base table */
  1689.                 execute @retcode = dbo.sp_MSsetartprocs @publication, @article
  1690.                 if @@ERROR <> 0 OR @retcode <> 0
  1691.                     goto FAILURE
  1692.  
  1693.                 /* Set the article status to be active so that Snapshot does not do this again */
  1694.                 select @statusid = 2 /* Active article */
  1695.                 update sysmergearticles set status = @statusid where artid = @artid
  1696.                 if @@ERROR <> 0 
  1697.                     goto FAILURE
  1698.             end
  1699.         
  1700. DONE_TRAN:
  1701.         /*
  1702.         ** For articles with subset filter clause - set the pub type to subset
  1703.         */
  1704.         if len(@subset_filterclause) > 0
  1705.             begin
  1706.                 execute @retcode = dbo.sp_MSsubsetpublication @publication
  1707.                 if @@ERROR <> 0 or @retcode<>0
  1708.                     goto FAILURE
  1709.             end                     
  1710.         /*
  1711.         ** Get distribution server information for remote RPC call.
  1712.         */
  1713.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  1714.            @distribdb   = @distribdb OUTPUT
  1715.         IF @@ERROR <> 0 or @retcode <> 0
  1716.             BEGIN
  1717.                 goto FAILURE
  1718.             END
  1719.  
  1720.         SELECT @dbname =  DB_NAME()
  1721.         
  1722.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  1723.             '.dbo.sp_MSadd_article'
  1724.         EXECUTE @retcode = @distproc
  1725.             @publisher = @@SERVERNAME,
  1726.             @publisher_db = @dbname,
  1727.             @publication = @publication,
  1728.             @article = @article,
  1729.             @destination_object = @destination_object,
  1730.             @source_owner = @source_owner,
  1731.             @source_object = @source_object,
  1732.             @description = @description
  1733.             -- @article_id = NULL
  1734.         IF @@ERROR <> 0 or @retcode <> 0
  1735.             BEGIN
  1736.                 goto FAILURE
  1737.             END
  1738.  
  1739.         COMMIT TRAN 
  1740.  
  1741.         /* If the article status is active adding the merge triggers to the base table */
  1742.          
  1743.         return (0)
  1744. FAILURE:
  1745.         RAISERROR (20009, 16, -1, @article, @publication)
  1746.         if @@TRANCOUNT > 0
  1747.         begin
  1748.             ROLLBACK TRANSACTION sp_addmergearticle
  1749.             COMMIT TRANSACTION
  1750.         end
  1751.         return (1)
  1752. go
  1753.  
  1754. exec dbo.sp_MS_marksystemobject sp_addmergearticle
  1755. go
  1756.  
  1757. grant execute on dbo.sp_addmergearticle to public
  1758. go
  1759.  
  1760. --------------------------------------------------------------------------------
  1761. --. sp_MSaddinitialpublication
  1762. --------------------------------------------------------------------------------
  1763. if exists (select * from sysobjects    where type = 'P'
  1764.     and name = 'sp_MSaddinitialpublication')
  1765.     drop procedure sp_MSaddinitialpublication
  1766. go
  1767.  
  1768. raiserror('Creating procedure sp_MSaddinitialpublication', 0,1)
  1769. GO
  1770.  
  1771. CREATE PROCEDURE sp_MSaddinitialpublication(
  1772.     @publisher                sysname,
  1773.     @publisher_db             sysname,
  1774.     @publication            sysname,             /* Name of the publication */
  1775.     @description            nvarchar(255),         /* Description of the publication */
  1776.     @pubid                     uniqueidentifier,    /* Publication ID */
  1777.     @retention                int,                /* Retention period of the publication */
  1778.     @sync_mode                int,                /* Sync mode of the publication */
  1779.     @allow_push                int,                /* does publication allow push ? */
  1780.     @allow_pull                int,                /* does publication allow pull ? */
  1781.     @allow_anonymous        int,                /* does publication allow anonymous ? */
  1782.     @centralized_conflicts    int,                 /* publication does centralized conflicts ? */
  1783.     @status                    int,                 /* publication's status */
  1784.     @snapshot_ready            int,                 /* publication snapshto_ready flag ? */
  1785.     @enabled_for_internet    int,                 /* publication enabled_for_internet flag ? */
  1786.     @publication_type        int                    /* a full publication or a partial one */
  1787.     ) AS
  1788.     
  1789.     SET NOCOUNT ON
  1790.     declare @retcode int
  1791.     declare @publisher_srvid int
  1792.     /*
  1793.     ** NOTE -- WORKAROUND ODBC BUG WHICH have not been reproed.
  1794.     */
  1795.     select @publication = RTRIM(@publication)
  1796.     select @publisher_db = RTRIM(@publisher_db)
  1797.     
  1798.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) 
  1799.         begin
  1800.         EXECUTE @retcode = dbo.sp_addserver @publisher, @duplicate_ok='duplicate_ok'
  1801.  
  1802.         IF @@error <> 0 OR @retcode <> 0
  1803.             BEGIN
  1804.                 RAISERROR (14042, 16, -1)
  1805.                 RETURN (1)
  1806.             END
  1807.         end                
  1808.  
  1809.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher)
  1810.     IF @publisher_srvid IS NULL
  1811.         BEGIN
  1812.             RAISERROR (14010, 16, -1)
  1813.             RETURN (1)
  1814.         END
  1815.     /*
  1816.     ** Check for subscribing permission
  1817.     */
  1818.     exec @retcode=sp_MSreplcheck_subscribe
  1819.     if @retcode<>0 or @@ERROR<>0 return (1)
  1820.     
  1821.     /*
  1822.     ** Populate the local copy of sysmergepublications
  1823.     */
  1824.     BEGIN TRAN
  1825.     save TRAN MSaddinitialpublication
  1826.     
  1827.     if exists (select * from sysmergepublications 
  1828.             where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db)
  1829.         begin 
  1830.             declare @pubid_local uniqueidentifier
  1831.             select @pubid_local = pubid 
  1832.                 from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  1833.  
  1834.             if exists (select * from sysmergesubscriptions 
  1835.                 where pubid = @pubid and srvid = @publisher_srvid and db_name = @publisher_db)
  1836.                     begin
  1837.                         delete from sysmergesubscriptions 
  1838.                             where pubid = @pubid and srvid = @publisher_srvid and db_name = @publisher_db
  1839.                         IF @@ERROR <> 0
  1840.                             BEGIN
  1841.                                 RAISERROR (14057, 16, -1)
  1842.                                 goto FAILURE
  1843.                             END
  1844.                     end
  1845.             update sysmergesubscriptions    SET pubid = @pubid where pubid = @pubid_local
  1846.             IF @@ERROR <> 0
  1847.                 BEGIN
  1848.                     RAISERROR (14057, 16, -1)
  1849.                     goto FAILURE
  1850.                 END
  1851.                 
  1852.             if @pubid <> @pubid_local
  1853.                 delete from sysmergesubscriptions where subid = @pubid
  1854.                 
  1855.             update sysmergesubscriptions    SET subid = @pubid where subid = @pubid_local
  1856.             IF @@ERROR <> 0
  1857.                 BEGIN
  1858.                     RAISERROR (14057, 16, -1)
  1859.                     goto FAILURE
  1860.                 END
  1861.  
  1862.             update sysmergesubscriptions    
  1863.                 SET partnerid = @pubid
  1864.                 where partnerid = @pubid_local
  1865.         
  1866.             IF @@ERROR <> 0
  1867.                 BEGIN
  1868.                     RAISERROR (14057, 16, -1)
  1869.                     goto FAILURE
  1870.                 END
  1871.  
  1872.             update sysmergepublications 
  1873.                 SET pubid = @pubid, 
  1874.                     name = @publication, 
  1875.                     description = @description, 
  1876.                     designmasterid = @pubid, 
  1877.                     retention = @retention, 
  1878.                     parentid = pubid, 
  1879.                     sync_mode = sync_mode, 
  1880.                     allow_push = @allow_push, 
  1881.                     allow_pull = @allow_pull, 
  1882.                     allow_anonymous = @allow_anonymous, 
  1883.                     centralized_conflicts = @centralized_conflicts,
  1884.                     status = @status,
  1885.                     snapshot_ready = @snapshot_ready,
  1886.                     enabled_for_internet = @enabled_for_internet,
  1887.                     publication_type = @publication_type
  1888.                 where name = @publication
  1889.                       and UPPER(publisher) = UPPER(@publisher)
  1890.                       and publisher_db = @publisher_db
  1891.         end
  1892.     else
  1893.         begin
  1894.             insert sysmergepublications(publisher, publisher_db,pubid, name, description, designmasterid, 
  1895.                 retention, parentid, sync_mode, allow_push, allow_pull, allow_anonymous, 
  1896.                 centralized_conflicts, status, snapshot_ready, enabled_for_internet, publication_type)
  1897.             values(@publisher, @publisher_db, @pubid, @publication, @description, @pubid, 
  1898.                 @retention, @pubid, @sync_mode, @allow_push, @allow_pull, @allow_anonymous, 
  1899.                 @centralized_conflicts, @status, @snapshot_ready, @enabled_for_internet, @publication_type)
  1900.         end
  1901.     IF @@ERROR <> 0
  1902.         BEGIN
  1903.             RAISERROR (14057, 16, -1)
  1904.             goto FAILURE
  1905.         END
  1906.     COMMIT TRAN
  1907.  
  1908.     RETURN (0)
  1909.  
  1910. FAILURE:
  1911.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  1912.     if @@TRANCOUNT > 0
  1913.     begin
  1914.         ROLLBACK TRANSACTION MSaddinitialpublication
  1915.         COMMIT TRANSACTION
  1916.     end
  1917.     RETURN (1)
  1918. go
  1919. exec dbo.sp_MS_marksystemobject sp_MSaddinitialpublication
  1920. go
  1921. grant exec on dbo.sp_MSaddinitialpublication to public
  1922. go
  1923.  
  1924. --------------------------------------------------------------------------------
  1925. --. sp_MSgetconflictinsertproc
  1926. --------------------------------------------------------------------------------
  1927. if exists (select * from sysobjects    where type = 'P'
  1928.     and name = 'sp_MSgetconflictinsertproc')
  1929.     drop procedure sp_MSgetconflictinsertproc
  1930. go
  1931.  
  1932. raiserror('Creating procedure sp_MSgetconflictinsertproc', 0,1)
  1933. GO
  1934.  
  1935. CREATE PROCEDURE sp_MSgetconflictinsertproc (
  1936.     @artid                 uniqueidentifier,
  1937.     @pubid                uniqueidentifier=NULL, --added for Sphinx SP3
  1938.     @output    int = 1
  1939.     ) AS
  1940.     declare @conflict_table sysname
  1941.     declare @dbname            sysname
  1942.     declare @conflict_proc    sysname
  1943.     declare @owner             sysname
  1944.     declare @object            sysname
  1945.     declare @retcode         int
  1946.     declare    @basetableid    int
  1947.     
  1948.     -- PARSENAME VARS
  1949.     declare @UnqualName     nvarchar(258)  --rightmost name node
  1950.     declare @QualName1      nvarchar(258)  
  1951.     declare @command        nvarchar(4000)
  1952.     declare @QualName2      nvarchar(258)  
  1953.     -- END PARSENAME VARS
  1954.  
  1955.     declare @guidstr varchar(40)
  1956.     exec @retcode=sp_MSguidtostr @artid, @guidstr out
  1957.     if @retcode<>0 or @@ERROR<>0 return (1)
  1958.     
  1959.     /*
  1960.     ** Check to see if current publication has permission
  1961.     */
  1962.     exec @retcode=sp_MSreplcheck_connection
  1963.         @artid = @artid
  1964.     if @retcode<>0 or @@ERROR<>0 return (1)
  1965.     
  1966.     select @conflict_table = conflict_table, @conflict_proc = ins_conflict_proc, @basetableid = objid from
  1967.         sysmergearticles where artid = @artid
  1968.  
  1969.     if @@ERROR <> 0
  1970.         return (1)
  1971.  
  1972.     -- Create an index on the conflict table if it doesn't have one
  1973.     if (OBJECT_ID(@conflict_table) is not null) and
  1974.         not exists (select * from sysindexes where id = OBJECT_ID(@conflict_table) and keys is not null)
  1975.         begin
  1976.         declare @rgcol sysname
  1977.         declare @indname sysname
  1978.         declare @quotedname sysname
  1979.         
  1980.         select @rgcol = QUOTENAME(name) from syscolumns where id = @basetableid and
  1981.                 ColumnProperty(id, name, 'isrowguidcol') = 1
  1982.         select @indname = 'uc_' + @conflict_table
  1983.         set @indname = QUOTENAME(@indname)
  1984.         set @quotedname = QUOTENAME(@conflict_table)
  1985.         exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname +
  1986.                 ' (' + @rgcol + ', origin_datasource)' )
  1987.         if @@error <> 0
  1988.             return (1)
  1989.         end
  1990.     if ((OBJECT_ID(@conflict_proc) is null) and (OBJECT_ID(@conflict_table) is not null))
  1991.         begin
  1992.  
  1993.         select @UnqualName = PARSENAME(@conflict_table, 1)
  1994.         select @QualName1 = PARSENAME(@conflict_table, 2)
  1995.         if @UnqualName IS NULL
  1996.              return 1
  1997.  
  1998.         -- fixup for variable length differences.  remove when vars expanded
  1999.         -- to new SQL SERVER 7.0 lengths
  2000.  
  2001.         select @owner =  @QualName1
  2002.         select @object = @UnqualName
  2003.  
  2004.         -- first set up the procedure name variable
  2005.         select @conflict_proc = 'sp_cft_' + @guidstr
  2006.         exec @retcode=sp_MSuniqueobjectname @conflict_proc , @conflict_proc output
  2007.         if @@ERROR <> 0 OR @retcode <> 0 
  2008.             return(1)
  2009.         set @dbname = db_name()
  2010.         if @owner is NULL
  2011.             set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , NULL, ' + @conflict_proc  + ' , ' + convert(nvarchar,@basetableid)
  2012.         else
  2013.             set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , ' + QUOTENAME(@owner) + ' , ' + @conflict_proc  + ' , ' + convert(nvarchar,@basetableid)
  2014.         exec @retcode = master..xp_execresultset @command, @dbname
  2015.         if @@ERROR<>0 OR @retcode<>0 
  2016.         begin
  2017.             return (1)
  2018.         end
  2019.         exec @retcode = dbo.sp_MS_marksystemobject  @conflict_proc 
  2020.         if @@ERROR<>0  return (1)
  2021.         exec ('grant exec on ' + @conflict_proc + ' to public')
  2022.         update sysmergearticles set ins_conflict_proc = @conflict_proc where artid = @artid
  2023.     end
  2024.  
  2025.     if @output = 1
  2026.         select @conflict_table, @conflict_proc
  2027.     if @@ERROR <> 0
  2028.         return (1)
  2029.     return (0)
  2030.     
  2031. go
  2032. exec dbo.sp_MS_marksystemobject sp_MSgetconflictinsertproc 
  2033. go
  2034. grant exec on dbo.sp_MSgetconflictinsertproc to public
  2035. go
  2036.  
  2037. --------------------------------------------------------------------------------
  2038. --. sp_MShelpcreatebeforetable
  2039. --------------------------------------------------------------------------------
  2040. if exists (select * from sysobjects    where type = 'P'
  2041.     and name = 'sp_MShelpcreatebeforetable')
  2042.     drop procedure sp_MShelpcreatebeforetable
  2043. go
  2044.  
  2045. raiserror('Creating procedure sp_MShelpcreatebeforetable', 0,1)
  2046. GO
  2047. create procedure sp_MShelpcreatebeforetable
  2048.     @objid int,
  2049.     @newname sysname
  2050. AS
  2051.     declare @command nvarchar(1000)
  2052.     declare @retcode int
  2053.     declare @include int
  2054.     declare @tablenick int
  2055.     declare @colpat nvarchar(130)
  2056.     declare @colname sysname
  2057.     declare @typename sysname
  2058.     declare @colid smallint
  2059.     declare @colidstr nvarchar(3)
  2060.     declare @status tinyint
  2061.     declare @len smallint
  2062.     declare @prec smallint
  2063.     declare @scale int
  2064.     declare @cMaxIndexLength int
  2065.     declare @isnullable tinyint
  2066.  
  2067.     set nocount on
  2068.  
  2069.     set @cMaxIndexLength= 900  
  2070.     select @tablenick = max(nickname) from sysmergearticles where objid = @objid
  2071.     if @tablenick is null return (1)
  2072.     
  2073.     -- create temp table to select the command text out of
  2074.     create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  2075.  
  2076.     set @command = 'create table ' + @newname + '('
  2077.     insert into #tempcmd (phase, cmdtext) values (1, @command)
  2078.     
  2079.     -- Loop over the columns and see which ones we include
  2080.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length,
  2081.          prec, scale, isnullable, colid from syscolumns
  2082.     where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid
  2083.     FOR READ ONLY
  2084.     
  2085.     open col_cursor
  2086.     fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  2087.     while (@@fetch_status <> -1)
  2088.         begin
  2089.         set @include = 0
  2090.         set @colpat = '%' + @colname + '%'
  2091.         if columnproperty( @objid, @colname , 'isrowguidcol')=1
  2092.             begin
  2093.             set @include = 1
  2094.             end
  2095.         else
  2096.             begin
  2097.             -- does updating this column change membership in a partial replica? 
  2098.             if exists (select * from sysmergearticles 
  2099.                 where objid = @objid and subset_filterclause like @colpat)
  2100.                 set @include = 1
  2101.             else if exists (select * from sysmergesubsetfilters
  2102.                 where art_nickname = @tablenick and join_filterclause like @colpat)
  2103.                 set @include = 1
  2104.             else if exists (select * from sysmergesubsetfilters
  2105.                  where join_nickname = @tablenick and join_filterclause like @colpat)
  2106.                 set @include = 1
  2107.             end
  2108.         -- If we want this column, map its type and insert a row to temp table
  2109.         if @include = 1
  2110.             begin
  2111.             if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  2112.                 set @len = @len/2
  2113.             exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  2114.             if @@ERROR<>0 or @retcode<>0 return (1)
  2115.             if @typename not in ('text', 'ntext','image')
  2116.                 begin
  2117.                 set @colname = QUOTENAME(@colname)
  2118.                 if @isnullable = 1
  2119.                     set @command = @colname + ' ' + @typename + ' NULL, '
  2120.                 else
  2121.                     set @command = @colname + ' ' + @typename + ' NOT NULL, '
  2122.                 
  2123.                 -- Insert the part of create table command for this column
  2124.                 insert into #tempcmd (phase, cmdtext) values (1, @command)
  2125.  
  2126.                 -- Insert a create index command
  2127.             if (@len <= @cMaxIndexLength)
  2128.                     begin
  2129.                     set @colidstr =convert(nvarchar(3), @colid)
  2130.                     set @command = 'create index ' + @newname + '_' + @colidstr + ' on ' + @newname +
  2131.                         ' (' + @colname + ')
  2132.                             '
  2133.                     insert into #tempcmd (phase, cmdtext) values (2, @command)
  2134.                     end
  2135.                 end
  2136.             end
  2137.         /* Repeat the loop with next column */
  2138.         fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  2139.         end
  2140.     close col_cursor
  2141.     deallocate col_cursor
  2142.  
  2143.     -- Insert last column, generation
  2144.     set @command = 'generation int NOT NULL)
  2145.         '
  2146.     insert into #tempcmd (phase, cmdtext) values (1, @command)
  2147.     set @command = 'create index ' + @newname + '_gen on ' + @newname + '(generation) 
  2148.         '
  2149.     insert into #tempcmd (phase, cmdtext) values (2, @command)
  2150.         
  2151.     select cmdtext from #tempcmd order by phase, step
  2152. go
  2153. exec dbo.sp_MS_marksystemobject sp_MShelpcreatebeforetable 
  2154. go
  2155.  
  2156. --------------------------------------------------------------------------------
  2157. --. sp_MShelpalterbeforetable
  2158. --------------------------------------------------------------------------------
  2159. if exists (select * from sysobjects    where type = 'P'
  2160.     and name = 'sp_MShelpalterbeforetable')
  2161.     drop procedure sp_MShelpalterbeforetable
  2162. go
  2163.  
  2164. raiserror('Creating procedure sp_MShelpalterbeforetable', 0,1)
  2165. GO
  2166. create procedure sp_MShelpalterbeforetable
  2167.     @objid int,
  2168.     @biname sysname
  2169. AS
  2170.     declare @command nvarchar(1000)
  2171.     declare @retcode int
  2172.     declare @include int
  2173.     declare @tablenick int
  2174.     declare @colpat nvarchar(130)
  2175.     declare @colname sysname
  2176.     declare @typename sysname
  2177.     declare @colid smallint
  2178.     declare @colidstr nvarchar(3)
  2179.     declare @status tinyint
  2180.     declare @len smallint
  2181.     declare @prec smallint
  2182.     declare @scale int
  2183.     declare @cMaxIndexLength int
  2184.     declare @isnullable tinyint
  2185.     declare @bi_objid int
  2186.     set nocount on
  2187.  
  2188.     select @tablenick = max(nickname) from sysmergearticles where objid = @objid
  2189.     if @tablenick is null 
  2190.         return (1)
  2191.  
  2192.     select @bi_objid = OBJECT_ID(@biname)        
  2193.     set @cMaxIndexLength= 900  
  2194.  
  2195.     -- Loop over the columns and see which ones we include
  2196.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length,
  2197.          prec, scale, isnullable, colid from syscolumns
  2198.     where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid
  2199.     FOR READ ONLY
  2200.     
  2201.     open col_cursor
  2202.     fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  2203.     while (@@fetch_status <> -1)
  2204.         begin
  2205.         set @include = 0
  2206.         set @colpat = '%' + @colname + '%'
  2207.  
  2208.         -- Is this column already in the before image table?
  2209.         if exists (select * from syscolumns where id = @bi_objid and name = @colname)
  2210.             begin
  2211.             goto fetchnext
  2212.             end
  2213.  
  2214.         -- does updating this column change membership in a partial replica? 
  2215.         if exists (select * from sysmergearticles 
  2216.             where objid = @objid and subset_filterclause like @colpat)
  2217.             set @include = 1
  2218.         else if exists (select * from sysmergesubsetfilters
  2219.             where art_nickname = @tablenick and join_filterclause like @colpat)
  2220.             set @include = 1
  2221.         else if exists (select * from sysmergesubsetfilters
  2222.             where join_nickname = @tablenick and join_filterclause like @colpat)
  2223.             set @include = 1
  2224.  
  2225.         -- If we want this column, map its type and insert a row to temp table
  2226.         if @include <> 1
  2227.             begin
  2228.             goto fetchnext
  2229.             end
  2230.         if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  2231.             set @len = @len/2
  2232.         exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  2233.         if @@ERROR<>0 or @retcode<>0 goto errlabel
  2234.         if @typename not in ('text', 'ntext','image')
  2235.         begin
  2236.             set @colname = QUOTENAME(@colname)
  2237.     
  2238.             -- Always make columns nullable when we add them because we might have
  2239.             -- existing rows in the before image table.
  2240.             set @command = 'alter table ' + @biname + ' ADD ' + @colname + ' ' + @typename + ' NULL '
  2241.             exec (@command)
  2242.                 if @@error <> 0 goto errlabel
  2243.         
  2244.             -- Insert a create index command if column is not too long
  2245.             if (@len <= @cMaxIndexLength)
  2246.             begin
  2247.                 set @colidstr =convert(nvarchar(3), @colid)
  2248.                  set @command = 'create index ' + @biname + '_' + @colidstr + ' on ' + @biname + ' (' + @colname + ')'
  2249.                 execute ( @command )
  2250.                 if @@ERROR<>0 goto errlabel
  2251.             end
  2252.         end            
  2253. fetchnext:
  2254.         /* Repeat the loop with next column */
  2255.         fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  2256.         end
  2257.     close col_cursor
  2258.     deallocate col_cursor
  2259.     return 0
  2260. errlabel:
  2261.     close col_cursor
  2262.     deallocate col_cursor
  2263.     return 1
  2264.  
  2265. go
  2266. exec dbo.sp_MS_marksystemobject sp_MShelpalterbeforetable 
  2267. go
  2268.  
  2269. --------------------------------------------------------------------------------
  2270. --. sp_MSread_resolver_clsid
  2271. --------------------------------------------------------------------------------
  2272. if exists (select * from sysobjects    where type = 'P'
  2273.     and name = 'sp_MSread_resolver_clsid')
  2274.     drop procedure sp_MSread_resolver_clsid
  2275. go
  2276.  
  2277. raiserror('Creating procedure sp_MSread_resolver_clsid', 0,1)
  2278. GO
  2279.  
  2280.  
  2281. create procedure sp_MSread_resolver_clsid (
  2282. @article_resolver sysname,
  2283. @resolver_clsid nvarchar(50)
  2284. )
  2285. AS
  2286.     RAISERROR (20020, 16, -1)
  2287.     RETURN (1)
  2288. GO
  2289. exec dbo.sp_MS_marksystemobject sp_MSread_resolver_clsid 
  2290. go
  2291.  
  2292.  
  2293. --------------------------------------------------------------------------------
  2294. --. sp_MSsetupbelongs
  2295. --------------------------------------------------------------------------------
  2296. if exists (select * from sysobjects    where type = 'P'
  2297.     and name = 'sp_MSsetupbelongs')
  2298.     drop procedure sp_MSsetupbelongs
  2299. go
  2300.  
  2301. raiserror('Creating procedure sp_MSsetupbelongs', 0,1)
  2302. GO
  2303.  
  2304. -- Modify temp table. No security check needed.
  2305. create procedure sp_MSsetupbelongs
  2306.     @publisher            sysname,
  2307.     @publisher_db        sysname,
  2308.     @publication         sysname,
  2309.     @genlist             varchar(1000),
  2310.     @commongen            int,
  2311.     @subissql            int
  2312.  
  2313. AS
  2314.     declare @pubid uniqueidentifier
  2315.     declare @temp_id int
  2316.     declare @retval int
  2317.     declare @tablenick int
  2318.     declare @tnstr nvarchar(12)
  2319.     declare @rowguid uniqueidentifier
  2320.     declare @rowguidstr nvarchar(40)
  2321.     declare @belongsname sysname
  2322.     declare @belongs_uniquename sysname
  2323.     declare @notbelongsname sysname
  2324.     declare @notbelongs_uniquename sysname
  2325.     declare @artnick    int
  2326.     declare @artnickstr nvarchar(10)
  2327.     declare @artviewobjid int
  2328.     declare @before_view_objid int
  2329.     declare @before_view_name sysname
  2330.     declare @procname sysname
  2331.     declare @sync_objid int
  2332. -- DEBUG declare @belongcnt int
  2333. -- DEBUG declare @nb_cnt int
  2334.     declare @artbaseobjid int
  2335.     declare @artviewname sysname
  2336.     declare @artviewowner sysname
  2337.  
  2338.     declare @commongenstr nvarchar(12)
  2339.     declare @partchangegen int
  2340.     declare @joinchangegen int
  2341.     declare @rgcol sysname
  2342.     declare @maxfilterid int
  2343.     declare @view_type int
  2344.     declare @temp_view int
  2345.     declare @retcode smallint
  2346.     declare @dynamic_join_cnt int
  2347.     
  2348.     /*
  2349.     ** To public
  2350.     */
  2351.     
  2352.     set @temp_view = 2
  2353. -- DEBUG insert into master.dbo.debuglog2 (publisher, pubdb, hostname, twhen, commongen, belong_cnt, nb_cnt, genlist) values
  2354. -- DEBUG (@publisher, @publisher_db, host_name(), getdate(), @commongen, NULL, NULL, @genlist)
  2355.  
  2356.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  2357.     set @commongenstr = convert(nchar(12), @commongen)
  2358.     select @dynamic_join_cnt = count(*) from sysmergesubsetfilters where pubid = @pubid and
  2359.         (UPPER(join_filterclause) like '%USER_%NAME%' or
  2360.          UPPER(join_filterclause) like '%USER_%ID%' or
  2361.          UPPER(join_filterclause) like '%SESSION_USER%' or
  2362.          UPPER(join_filterclause) like '%SYSTEM_USER%')
  2363.          
  2364.     /* Set up the ##belong and ##notbelong tables; return names as rowset */
  2365.     /* step 1 make temptable names, create tables */
  2366.     set @rowguid = newid()
  2367.     exec @retcode=sp_MSguidtostr @rowguid, @rowguidstr out
  2368.     if @retcode<>0 or @@ERROR<>0 return (1)
  2369.     
  2370.     set @belongsname = '##belong' + @rowguidstr
  2371.     set @belongs_uniquename = 'bunique_' + @rowguidstr
  2372.     exec @retcode = dbo.sp_MSuniquetempname @belongsname, @belongsname out
  2373.     IF @@ERROR<>0 OR @retcode<>0 return (1)
  2374.     create table #belong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL,
  2375.         partchangegen int null, joinchangegen int null, skippedexpand int null)
  2376.     create index #indbelong on #belong (rowguid, tablenick)
  2377.     
  2378.     exec ('create table ' + @belongsname + ' (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  2379.         generation int NULL, lineage varbinary(255) NULL, colv varbinary(2048) NULL) ')
  2380.     if @@ERROR <>0 return (1)
  2381.     create table #notbelong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  2382.         flag int NOT NULL, partchangegen int null, joinchangegen int null, type int default 5)
  2383.     create index #indnbelong on #notbelong (tablenick, rowguid)
  2384.     create table #genlist (generation int)
  2385.     exec ('insert into #genlist select distinct generation from MSmerge_genhistory where
  2386.             generation in (' + @genlist + ')')
  2387.             
  2388.     set @notbelongsname = '##notbelong' + @rowguidstr
  2389.     set @notbelongs_uniquename = 'nbunique_' + @rowguidstr
  2390.     exec @retcode = dbo.sp_MSuniquetempname @notbelongsname, @notbelongsname out
  2391.     IF @@ERROR<>0 OR @retcode<>0 return (1)
  2392.     exec ('create table ' + @notbelongsname + ' (bookmark int identity  primary key NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  2393.         generation int NULL, lineage varbinary(255) NULL, type tinyint NOT NULL) ')
  2394.     if @@ERROR <>0 return (1)
  2395.     create table #temp_cont (temp_id int identity NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  2396.             partchangegen int null, joinchangegen int null)
  2397.  
  2398.     /* step 2 setup pass through MSmerge_contents */
  2399.     /* article with permanent views can be handled with bulk inserts */
  2400.     set @artnick = 0
  2401.     set rowcount 0
  2402.     
  2403.     /* Get first article, go into loop */
  2404.     select @artnick = min(nickname) from sysmergearticles where pubid = @pubid and
  2405.          nickname > @artnick
  2406.  
  2407.     if @@ERROR <>0 return (1)        
  2408.  
  2409.  
  2410.     while (@artnick is not null)
  2411.         begin
  2412.         set @artnickstr = convert(nchar(10), @artnick)
  2413.         select @artviewobjid = sync_objid, @artbaseobjid = objid, @view_type = view_type,
  2414.             @procname = view_sel_proc, @sync_objid=sync_objid, @before_view_objid = before_view_objid from sysmergearticles where
  2415.             pubid = @pubid and nickname = @artnick
  2416.         /* Get name of rowguidcol. Aliasing doesn't work through a view. */
  2417.         select @rgcol = name from syscolumns where id = @artbaseobjid and ColumnProperty(@artbaseobjid, name, 'isrowguidcol') = 1
  2418.  
  2419.         /* UNDONE get view type from sysmergearticle to see if permanent view to use */
  2420.         set @artviewname = NULL
  2421.         if @view_type <> @temp_view
  2422.             select @artviewname = name, @artviewowner = user_name(uid) from sysobjects where
  2423.                 id = @artviewobjid
  2424.         if (@procname is not null)
  2425.             begin
  2426.             exec @retcode = @procname @artnick
  2427.             if @@ERROR <>0 or @retcode <> 0 return (1)
  2428.             end
  2429.         else
  2430.             begin
  2431.             delete from #temp_cont
  2432.             exec ('insert into #temp_cont (tablenick, rowguid, partchangegen, joinchangegen) 
  2433.                         select tablenick, rowguid, partchangegen, joinchangegen from MSmerge_contents where
  2434.                         tablenick  = ' + @artnickstr + ' and generation in (' +
  2435.                     @genlist + ') ')
  2436.             if @@ERROR <>0 return (1)        
  2437.             set @temp_id = 0
  2438.             select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
  2439.             while (@temp_id is not null)
  2440.                 begin
  2441.                 select @tablenick = tablenick, @rowguid = rowguid,
  2442.                    @partchangegen = partchangegen, @joinchangegen = joinchangegen 
  2443.                     from #temp_cont where temp_id = @temp_id
  2444.                 set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''
  2445.                 exec @retcode = dbo.sp_MSbelongs @publisher, @publisher_db,    @publication, @tablenick, @rowguid, @retval    output, 0
  2446.                 if @@ERROR <>0 or @retcode <> 0 return (1)
  2447.                 if @retval = 1
  2448.                     begin
  2449.                     insert into #belong (tablenick, rowguid, flag, partchangegen, joinchangegen) values
  2450.                             (@artnick, @rowguid, 0, @partchangegen, @joinchangegen)
  2451.                     if @@ERROR <>0 return (1)    
  2452.                     end
  2453.  
  2454.                 else
  2455.                     begin
  2456.                     /* Checking partchangegen will tell us if we need to insert this */
  2457.                     if @partchangegen > @commongen
  2458.                         insert into #notbelong (tablenick, rowguid, flag) values
  2459.                             (@artnick, @rowguid, 0)
  2460.                     end
  2461.  
  2462.                 select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
  2463.                 end
  2464.  
  2465.             end
  2466.         /* Put changes in #notbelong  that aren't in #belong and have a relevant partchangegen    */
  2467.         -- If publication has before image tables, we should screen changes using the before image tables
  2468.         if @before_view_objid is not null
  2469.             begin
  2470.             set @before_view_name = OBJECT_NAME(@before_view_objid)
  2471.             execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen)
  2472.                 select tablenick, c.rowguid, 0, partchangegen, joinchangegen
  2473.                     from MSmerge_contents c, #genlist g where c.generation = g.generation
  2474.                     and partchangegen > ' + @commongenstr + ' and tablenick = ' + @artnickstr + ' and
  2475.                     rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ') and
  2476.                     rowguid not in (select rowguid from #belong)')
  2477.             if @@ERROR <>0 return (1)
  2478.             
  2479.             /* Add tombstones to ##notbelong */
  2480.             execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) 
  2481.                 select tablenick, rowguid,  0, generation, generation, type from
  2482.                 MSmerge_tombstone where tablenick = ' + @artnickstr + ' and
  2483.                     rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ') and generation in (' + @genlist + ' ) ')
  2484.             if @@ERROR <>0 return (1)
  2485.  
  2486.             end
  2487.         else
  2488.             begin 
  2489.             insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen)
  2490.                 select tablenick, c.rowguid, 0, partchangegen, joinchangegen
  2491.                     from MSmerge_contents c, #genlist g where c.generation = g.generation
  2492.                     and partchangegen > @commongen and tablenick = @artnick and
  2493.                     rowguid not in (select rowguid from #belong)
  2494.             if @@ERROR <>0 return (1)
  2495.             execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) 
  2496.                 select tablenick, rowguid,  0, generation, generation, type from
  2497.                 MSmerge_tombstone where tablenick = ' + @artnickstr + ' and generation in (' + @genlist + ' ) ')
  2498.             if @@ERROR <>0 return (1)
  2499.             end
  2500.         /* Move on to next article, repeat while loop */
  2501.         select @artnick = min(nickname) from sysmergearticles where pubid = @pubid and
  2502.              nickname > @artnick
  2503.         end
  2504.  
  2505.     drop table #temp_cont 
  2506.  
  2507.     /* Optimization: If joinchangegen and partchange are both null or < common gen,
  2508.     ** it is not necessary to expand #belong for that particular row.
  2509.     */
  2510.     
  2511.     select @maxfilterid = max(join_filterid) from sysmergesubsetfilters
  2512.  
  2513.     if @maxfilterid is not null
  2514.         begin
  2515.         update #belong set flag = @maxfilterid, skippedexpand = 1 where
  2516.             ((joinchangegen is null or joinchangegen <= @commongen) and
  2517.              (partchangegen is null or partchangegen <= @commongen))
  2518.  
  2519.         /* Expand the #belong temptable */
  2520.         exec @retcode = dbo.sp_MSexpandbelongs @pubid
  2521.         if @@ERROR<>0 OR @retcode<>0 return (1)
  2522.         end
  2523.         
  2524.     /* transfer rows from local temp to global temp */
  2525.     exec ('insert into ' + @belongsname + ' (tablenick, rowguid, generation, lineage, colv) 
  2526.         select distinct b.tablenick, b.rowguid, c.generation, c.lineage, c.colv1 from
  2527.         #belong b left outer join MSmerge_contents c  
  2528.         on  c.tablenick = b.tablenick and c.rowguid = b.rowguid order by b.tablenick, b.rowguid')
  2529.     if @@ERROR <>0 return (1)    
  2530.  
  2531.     /* If subscriber is sql server, we don't have to expand belongs */
  2532.     if @subissql = 0 or @dynamic_join_cnt > 0
  2533.         begin
  2534.         /* Expand the #notbelong temptable */
  2535.         exec dbo.sp_MSexpandnotbelongs @pubid
  2536.         end
  2537.  
  2538.     /* transfer rows from local temp to global temp */
  2539.     exec ('insert into ' + @notbelongsname + ' (tablenick, rowguid, generation, lineage, type) 
  2540.         select distinct b.tablenick, b.rowguid, coalesce (c.generation, t.generation), coalesce(c.lineage, t.lineage), b.type from
  2541.         #notbelong b left outer join MSmerge_contents c  
  2542.          on  c.tablenick = b.tablenick and c.rowguid = b.rowguid
  2543.         left outer join MSmerge_tombstone t on t.tablenick = b.tablenick and t.rowguid = b.rowguid
  2544.             order by b.tablenick DESC, b.rowguid ASC')
  2545.     if @@ERROR <>0 return (1)    
  2546.  
  2547.     -- this index will be useful in sp_MSenumpartialchanges
  2548.     exec ('create index nc1belongstable on ' + @belongsname + ' (tablenick, rowguid) with FILLFACTOR = 100')
  2549.     if @@ERROR <>0    
  2550.         return (1)
  2551.  
  2552.     -- this index will be useful in sp_MSenumpartialdeletes
  2553.     exec ('create index nc1notbelongstable on ' + @notbelongsname + ' (tablenick, rowguid) with FILLFACTOR = 100')
  2554.     if @@ERROR <>0    
  2555.         return (1)
  2556.     
  2557.  
  2558. -- DEBUG select @belongcnt = count(*) from #belong
  2559. -- DEBUG select @nb_cnt = count(*) from #notbelong
  2560.     drop table #notbelong
  2561.  
  2562. -- DEBUG insert into master.dbo.debuglog2 (publisher, pubdb, hostname, twhen, commongen, belong_cnt, nb_cnt, genlist) values
  2563. -- DEBUG (@publisher, @publisher_db, host_name(), getdate(), @commongen, @belongcnt, @nb_cnt, @genlist)
  2564.  
  2565.     if not exists (select * from #belong)
  2566.         select @belongsname, @notbelongsname, -1
  2567.     else
  2568.         select distinct @belongsname, @notbelongsname, tablenick from #belong
  2569.     drop table #belong
  2570.     return (0)
  2571. go
  2572.  
  2573. exec dbo.sp_MS_marksystemobject sp_MSsetupbelongs
  2574. go
  2575. grant exec on dbo.sp_MSsetupbelongs to public
  2576. go
  2577.  
  2578. --------------------------------------------------------------------------------
  2579. --. sp_MSmakesystableviews
  2580. --------------------------------------------------------------------------------
  2581. if exists (select * from sysobjects    where type = 'P'
  2582.     and name = 'sp_MSmakesystableviews')
  2583.     drop procedure sp_MSmakesystableviews
  2584. go
  2585.  
  2586. raiserror('Creating procedure sp_MSmakesystableviews', 0,1)
  2587. GO
  2588.  
  2589.  
  2590. create procedure sp_MSmakesystableviews
  2591.     (@publication sysname)
  2592. AS
  2593.     declare @guidstr         nvarchar(40)
  2594.     declare @pubid          uniqueidentifier
  2595.     declare @contentsview     sysname 
  2596.     declare @tombstoneview     sysname
  2597.     declare @genhistoryview    sysname
  2598.     declare @filtersview    sysname
  2599.     declare @retcode smallint
  2600.     declare @dbname            sysname
  2601.     declare    @command        nvarchar(500)
  2602.     
  2603.     /*
  2604.     ** Check to see if current publication has permission
  2605.     */
  2606.     exec @retcode=sp_MSreplcheck_publish
  2607.     if @retcode<>0 or @@ERROR<>0 return (1)
  2608.     
  2609.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  2610.     if @pubid is null
  2611.         BEGIN
  2612.             RAISERROR (20026, 16, -1, @publication)
  2613.             RETURN (1)
  2614.         END
  2615.  
  2616.     exec @retcode = dbo.sp_MSguidtostr @pubid, @guidstr out
  2617.     if @@ERROR<>0 OR @retcode<>0 return (1)
  2618.     select @contentsview = 'cont' + @guidstr
  2619.     select @tombstoneview = 'ts' + @guidstr
  2620.     select @genhistoryview = 'gh' + @guidstr
  2621.     select @filtersview = 'filt' + @guidstr
  2622.  
  2623.     set @guidstr = '''' + convert(nchar(36), @pubid) + ''''
  2624.     
  2625.     exec @retcode = dbo.sp_MSuniqueobjectname @tombstoneview, @tombstoneview out
  2626.     if @@ERROR<>0 OR @retcode<>0 return (1)
  2627.     exec @retcode = dbo.sp_MSuniqueobjectname @contentsview, @contentsview out
  2628.     if @@ERROR<>0 OR @retcode<>0 return (1)
  2629.     exec @retcode = dbo.sp_MSuniqueobjectname @genhistoryview, @genhistoryview out
  2630.     if @@ERROR<>0 OR @retcode<>0 return (1)
  2631.     exec @retcode = dbo.sp_MSuniqueobjectname @filtersview, @filtersview out
  2632.     if @@ERROR<>0 OR @retcode<>0 return (1)
  2633.  
  2634.     /* generate view for MSmerge_contents qualified by the pubid */
  2635.     set @command = 'sp_MSmakectsview ' + QUOTENAME(@publication) + ' , ' + @contentsview
  2636.     set @dbname = db_name()
  2637.  
  2638.     exec @retcode = master..xp_execresultset @command, @dbname
  2639.     if @@ERROR<>0 OR @retcode <>0 return (1)
  2640.  
  2641.     /* 
  2642.     ** generate the view for MSmerge_tombstone. In SP2, the change was made to make the view 
  2643.     ** return 0 rows since it is unnecessary and expensive to propagate the tombstones.
  2644.     ** In order to leave all the other moving parts unchanged, we decided to let the view 
  2645.     ** return 0 rows.
  2646.     */
  2647.     exec ('create view ' + @tombstoneview + ' as select * from MSmerge_tombstone where 1 = 2 and
  2648.             tablenick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' +
  2649.             @guidstr + ')')
  2650.     if @@ERROR <>0 
  2651.         begin
  2652.             return (1)
  2653.         end
  2654.  
  2655.     /* take care of the potential dup-key problem on (guidsrc-pubid) */
  2656.     if exists (select * from MSmerge_genhistory gen1, MSmerge_genhistory gen2 where
  2657.         gen1.guidsrc=gen2.guidsrc and gen1.generation=gen2.generation and 
  2658.             gen1.pubid is not null and gen2.pubid is not null and gen1.pubid<>gen2.pubid)         
  2659.         begin
  2660.             delete gen1 from MSmerge_genhistory gen1, MSmerge_genhistory gen2 
  2661.                 where gen1.guidsrc=gen2.guidsrc and gen1.generation=gen2.generation
  2662.                     and gen1.pubid is not null and gen2.pubid is not null and gen1.pubid>gen2.pubid
  2663.             if @@ERROR<>0
  2664.                 return (1)
  2665.         end
  2666.  
  2667.     exec ('create view ' + @genhistoryview + '(guidsrc, guidlocal, pubid, generation,
  2668.             art_nick, nicknames, coldate) as select DISTINCT guidsrc, guidlocal, CONVERT(uniqueidentifier, ' 
  2669.             + @guidstr + '), generation, art_nick, nicknames, coldate  from MSmerge_genhistory
  2670.             where guidlocal <> ''00000000-0000-0000-0000-000000000000'' and (art_nick = 0 or art_nick is NULL or
  2671.                     art_nick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' +
  2672.             @guidstr + ')) ')
  2673.     if @@ERROR <>0
  2674.         begin
  2675.             return (1)
  2676.         end
  2677.  
  2678.     exec ('create view ' + @filtersview + ' as select * from sysmergesubsetfilters where convert(nchar(36), pubid) = ' +
  2679.             @guidstr)
  2680.     if @@ERROR <>0
  2681.         begin
  2682.             return (1)
  2683.         end
  2684.  
  2685.     set nocount on
  2686.     select @contentsview, @tombstoneview, @genhistoryview, @filtersview
  2687.     return (0)
  2688. go
  2689. exec dbo.sp_MS_marksystemobject sp_MSmakesystableviews
  2690. go
  2691. grant exec on dbo.sp_MSmakesystableviews to public
  2692. go
  2693.  
  2694.  
  2695. --------------------------------------------------------------------------------
  2696. --. sp_MSmakeviewproc
  2697. --------------------------------------------------------------------------------
  2698. if exists (select * from sysobjects    where type = 'P'
  2699.     and name = 'sp_MSmakeviewproc')
  2700.     drop procedure sp_MSmakeviewproc
  2701. go
  2702.  
  2703.  
  2704. raiserror('Creating procedure sp_MSmakeviewproc', 0,1)
  2705. GO
  2706.  
  2707. create procedure sp_MSmakeviewproc 
  2708.     (@viewname sysname, @ownername sysname, @procname nvarchar(290), @rgcol sysname, @source_id int)
  2709. as
  2710. declare @retcode             smallint
  2711. declare @varname            nvarchar(10)
  2712. declare @cmdpiece            nvarchar(4000)
  2713. declare @column_list        nvarchar(4000)
  2714. declare @col_name            sysname
  2715.  
  2716. set nocount on
  2717.  
  2718. if EXISTS (select name from syscolumns where id=@source_id and iscomputed=1)
  2719. BEGIN
  2720.     select @column_list = ''
  2721.     DECLARE column_cursor CURSOR LOCAL FAST_FORWARD FOR
  2722.         select name from syscolumns where id=@source_id and iscomputed<>1
  2723.     FOR READ ONLY
  2724.     open column_cursor
  2725.     fetch next from column_cursor into @col_name
  2726.     WHILE (@@fetch_status <> -1)
  2727.     BEGIN
  2728.             if LOWER(@col_name)='rowguid' 
  2729.                 select @col_name = 'v.rowguid' --Use alias to avoid conflict with #cont table
  2730.             else
  2731.                 set @col_name = QUOTENAME(@col_name)
  2732.             if @column_list=''
  2733.                 select @column_list = @col_name
  2734.             else
  2735.                 select @column_list = @column_list + ', ' + @col_name            
  2736.             fetch next from column_cursor into @col_name            
  2737.     END
  2738.     close column_cursor
  2739.     deallocate column_cursor
  2740.  
  2741.     if @column_list=''
  2742.     begin
  2743.         RAISERROR(21125, 16, -1)
  2744.         return (1)
  2745.     end
  2746. END
  2747. else 
  2748.     select @column_list = '*'
  2749.  
  2750. select @procname=QUOTENAME(@procname)
  2751.  
  2752. set @cmdpiece = 'create procedure dbo.' + @procname + ' (@tablenick int, @max_rows int = NULL,
  2753.     @guidlast uniqueidentifier = NULL) 
  2754.     AS
  2755.  
  2756.     set nocount on
  2757.     set rowcount 0
  2758.     if  @max_rows is not null
  2759.         begin
  2760.         -- used to select data for initial pop. of subscriber for dynamic filtered publication
  2761.         set rowcount @max_rows
  2762.         declare @lin varbinary (255)
  2763.         declare @cv varbinary (2048)
  2764.         declare @replnick int
  2765.         declare @objid int
  2766.         declare @ccols int
  2767.  
  2768.         select @objid = objid from sysmergearticles where nickname = @tablenick
  2769.         select @ccols = max(colid) from syscolumns where id = @objid
  2770.         
  2771.         exec dbo.sp_MSgetreplnick @nickname = @replnick out
  2772.         if (@@error <> 0) or @replnick IS NULL 
  2773.                 begin
  2774.             RAISERROR (14055, 11, -1)
  2775.             RETURN(1)
  2776.             end                 
  2777.         set @lin = { fn UPDATELINEAGE(0x0, @replnick) }
  2778.         set @cv = { fn INITCOLVS(@ccols, @replnick) }
  2779.  
  2780.         select @tablenick, v.' + @rgcol + ', coalesce (c.generation,1), 
  2781.             coalesce (c.lineage, @lin), coalesce (c.colv1, @cv), ' + @column_list + ' from ' +
  2782.                  QUOTENAME(@ownername) + '.' +
  2783.                     QUOTENAME(@viewname) + ' v left outer join  MSmerge_contents c on
  2784.                       v.' + @rgcol + ' = c.rowguid and c.tablenick = @tablenick where v.' + @rgcol + ' > @guidlast 
  2785.                      order by v.' + @rgcol + '
  2786.         return (1)        
  2787.         end
  2788.     insert into #belong (tablenick, rowguid, flag, partchangegen, joinchangegen)
  2789.         select ct.tablenick, ct.rowguid, 0, ct.partchangegen, ct.joinchangegen
  2790.                     from  MSmerge_contents ct, #genlist g, ' + QUOTENAME(@ownername) + '.' +
  2791.                     QUOTENAME(@viewname) + ' v where ct.tablenick = @tablenick
  2792.                     and ct.generation = g.generation 
  2793.                     and ct.rowguid = v.' + @rgcol + '
  2794.  
  2795.         UNION
  2796.  
  2797.         select ct.tablenick, ct.rowguid, 0, ct.partchangegen, ct.joinchangegen
  2798.                     from  MSmerge_contents ct, #genlist g, ' + QUOTENAME(@ownername) + '.' +
  2799.                     QUOTENAME(@viewname) + ' v where ct.tablenick = @tablenick
  2800.                     and ct.partchangegen = g.generation
  2801.                     and ct.rowguid = v.' + @rgcol + '
  2802.  
  2803.     if @@ERROR <> 0
  2804.         begin
  2805.         RAISERROR(''Error selecting from view'' , 16, -1)
  2806.         return (1)    
  2807.         end'
  2808.  
  2809.             
  2810. exec (@cmdpiece)
  2811. exec dbo.sp_MS_marksystemobject @procname
  2812. exec ('grant exec on ' + @procname + ' to public')
  2813. go
  2814.             
  2815. exec dbo.sp_MS_marksystemobject sp_MSmakeviewproc 
  2816. go
  2817. grant exec on dbo.sp_MSmakeviewproc to public
  2818. go
  2819.  
  2820. --------------------------------------------------------------------------------
  2821. --. sp_MSmakeviewproc
  2822. --------------------------------------------------------------------------------
  2823. if exists (select * from sysobjects    where type = 'P'
  2824.     and name = 'sp_MSdelsubrows')
  2825.     drop procedure sp_MSdelsubrows
  2826. go
  2827.  
  2828. raiserror('Creating procedure sp_MSdelsubrows', 0,1)
  2829. GO
  2830.  
  2831. create PROCEDURE sp_MSdelsubrows 
  2832.     (@rowguid         uniqueidentifier,
  2833.     @tablenick     int,
  2834.     @metadata_type tinyint, /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred */
  2835.     @lineage_old varbinary(255),
  2836.     @generation int,
  2837.     @lineage_new varbinary(255),
  2838.     @pubid uniqueidentifier = NULL,
  2839.     @rowsdeleted INT = NULL OUTPUT)
  2840.  
  2841. as
  2842.     set nocount on
  2843.     declare @success int 
  2844.     declare @tablename         nvarchar(258)
  2845.     declare @rowguidstr        nvarchar(40)
  2846.     declare @match             int
  2847.     declare @new_metatype    tinyint
  2848.     declare @retcode         smallint
  2849.     declare @reason         nvarchar(255)
  2850.     declare @procname         nvarchar(258)
  2851.     declare @ownername        sysname
  2852.     /* By default this sp should delete exactly one row */
  2853.     set    @rowsdeleted = 1
  2854.  
  2855.     /*
  2856.     ** Check to see if current publication has permission
  2857.     */
  2858.     exec @retcode=sp_MSreplcheck_connection
  2859.         @tablenick = @tablenick
  2860.     if @retcode<>0 or @@ERROR<>0 return (1)
  2861.     
  2862.     select @success = 0
  2863.     /* Parameter validation */
  2864.     if (@rowguid is null)
  2865.         begin
  2866.         RAISERROR(14043, 16, -1, '@rowguid')
  2867.         return (0)
  2868.         end
  2869.     if (@tablenick is null)
  2870.         begin
  2871.         RAISERROR(14043, 16, -1, '@tablenick')
  2872.         return (0)
  2873.         end
  2874.     if @pubid is NULL
  2875.         exec @retcode = dbo.sp_MStablenamefromnick    @tablenick, @tablename output
  2876.     else
  2877.         exec @retcode = dbo.sp_MStablenamefromnick    @tablenick, @tablename output, @pubid
  2878.     if @@ERROR<>0 return (0)
  2879.  
  2880.     if (@tablename is null)
  2881.         begin
  2882.         RAISERROR(14043, 16, -1, '@tablename')
  2883.         return (0)
  2884.         end
  2885.     if (@lineage_new is null)
  2886.         begin
  2887.         RAISERROR(14043, 16, -1, '@lineage_new')
  2888.         return (0)
  2889.         end
  2890.  
  2891.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  2892.         begin
  2893.         RAISERROR(20054 , 16, -1)
  2894.         return (0)
  2895.         end
  2896.     set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''
  2897.  
  2898. -- DEBUG    insert into master.dbo.debuglog(tablenick, rowguid, type, twhen, comment) values
  2899. -- DEBUG    (@tablenick, @rowguid, @metadata_type, getdate(), 'sp_MSdelsubrows')
  2900.  
  2901.     -- Are we just changing the type of a tombstone?
  2902.     if (@metadata_type = 5 and exists (select * from MSmerge_tombstone where
  2903.         rowguid = @rowguid and tablenick = @tablenick))
  2904.         begin
  2905.         set @success = 1
  2906.         return @success
  2907.         end
  2908.  
  2909.     -- Are we just changing the type of a tombstone?
  2910.     if (@metadata_type = 1 and exists (select * from MSmerge_tombstone where
  2911.         rowguid = @rowguid and tablenick = @tablenick))
  2912.         begin
  2913.         set @reason = formatmessage (20562) -- User delete
  2914.         update MSmerge_tombstone set type = @metadata_type, reason = @reason where
  2915.             rowguid = @rowguid and tablenick = @tablenick
  2916.         set @success = 1
  2917.         return @success
  2918.         end
  2919.  
  2920.  
  2921.     -- Are we just changing the type of a tombstone?
  2922.     if (@metadata_type = 6 and exists (select * from MSmerge_tombstone where
  2923.         rowguid = @rowguid and tablenick = @tablenick))
  2924.         begin
  2925.         set @reason = formatmessage (20564) -- System deleted
  2926.         update MSmerge_tombstone set type = @metadata_type, reason = @reason where
  2927.             rowguid = @rowguid and tablenick = @tablenick
  2928.         set @success = 1
  2929.         return @success
  2930.         end
  2931.  
  2932.     -- begin transaction and lock row that we plan to delete
  2933.     begin transaction
  2934.  
  2935.         select @ownername = user_name(uid) from sysobjects where id = object_id(@tablename)
  2936.         select @procname = select_proc from sysmergearticles where objid = object_id(@tablename)  and pubid = @pubid
  2937.         exec @retcode = @procname @type =8, @rowguid=@rowguid
  2938.  
  2939.         select @success = 2
  2940.         
  2941.     if @metadata_type = 5
  2942.         begin
  2943.         set @match = 1
  2944.         set @new_metatype = 5
  2945.         end
  2946.     else if @metadata_type = 6
  2947.         begin
  2948.         set @match = 1
  2949.         set @new_metatype = 6
  2950.         end
  2951.     else
  2952.         begin
  2953.         exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
  2954.  
  2955.         set @new_metatype = 1
  2956.         end
  2957.     if (@match = 1)
  2958.         begin
  2959.         
  2960.         /* If there are any joinfilters with this as the join table, try to expand to deleting
  2961.         ** a set of related rows.
  2962.         */
  2963.         if (exists (select * from sysmergesubsetfilters where pubid = @pubid and
  2964.                         join_nickname = @tablenick))
  2965.             begin
  2966.             declare @tn int
  2967.             declare @table_name sysname
  2968.             
  2969.             set @reason = formatmessage (20563) -- Moved out of partial range
  2970.             /* create temp and put in our tablenick, rowguid */
  2971.             create table #notbelong (tablenick int NOT NULL,
  2972.                 rowguid uniqueidentifier NOT NULL, flag int NOT NULL)
  2973.             create index #indnbelong on #notbelong (rowguid)
  2974.             insert into #notbelong (tablenick, rowguid, flag) values
  2975.                     (@tablenick, @rowguid, 0)
  2976.                     
  2977.             /* call expand proc */
  2978.             exec @retcode = dbo.sp_MSexpandsubsnb @pubid
  2979.  
  2980.             select @rowsdeleted = count(*) from #notbelong
  2981.             
  2982.             select @tn = max(tablenick) from #notbelong where flag > -1
  2983.             while @tn is not null
  2984.                 begin
  2985.                 exec @retcode = dbo.sp_MStablenamefromnick @tn, @table_name out, @pubid
  2986.                 /* delete all rows indicated by the temp table */
  2987.                 exec ('delete from ' + @table_name + ' where RowGuidCol in 
  2988.                     (select rowguid from #notbelong)' )
  2989.                 /* change tombstone type for those rows */
  2990.                 update MSmerge_tombstone set type = 5, reason = @reason where tablenick = @tn and
  2991.                     rowguid in (select rowguid from #notbelong)
  2992.                     
  2993.                 /* move on to next nickname - decreasing makes delete order correct */
  2994.                 update #notbelong set flag = -1 where tablenick = @tn
  2995.                 select @tn = max(tablenick) from #notbelong where flag > -1
  2996.                 end
  2997.  
  2998.             /* drop temp, set success */
  2999.             drop table #notbelong
  3000.             exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  3001.             select @success = 1
  3002.             end
  3003.         else
  3004.             begin
  3005.         
  3006.             /*
  3007.             ** select_proc makes a delete with @type = 5, despite its name. 
  3008.             */
  3009.             exec @retcode = @procname @type =5, @rowguid=@rowguid
  3010.         
  3011.             if (@@error = 0 and @@rowcount = 1)
  3012.                 begin
  3013.                 exec dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  3014.                 select @success = 1
  3015.                 end
  3016.             else
  3017.                 select @success = 3
  3018.             end
  3019.         end
  3020.     commit
  3021.     return (@success)
  3022. go
  3023. exec dbo.sp_MS_marksystemobject sp_MSdelsubrows 
  3024. go
  3025. grant exec on dbo.sp_MSdelsubrows to public
  3026. go
  3027.  
  3028.  
  3029. --------------------------------------------------------------------------------
  3030. --. sp_vupgrade_mergetables
  3031. --------------------------------------------------------------------------------
  3032. if exists (select * from sysobjects    where type = 'P'
  3033.     and name = 'sp_vupgrade_mergetables')
  3034.     drop procedure sp_vupgrade_mergetables
  3035. go
  3036.  
  3037. raiserror('Creating procedure sp_vupgrade_mergetables', 0,1)
  3038. GO
  3039. create procedure sp_vupgrade_mergetables
  3040. as
  3041.  
  3042.     -- this raiserror makes sp_vupgrade_replication.out file easier to read
  3043.     raiserror('sp_vupgrade_mergetables', 0,1)
  3044.  
  3045.     DECLARE @table_name sysname
  3046.  
  3047.     if (exists (select * from sysobjects where name = 'sysmergearticles'))
  3048.         begin
  3049.         -- Columns have been added to the sysmergearticles table
  3050.         if not exists (select * from syscolumns where id = object_id('sysmergearticles') and
  3051.                         name = 'gen_cur')
  3052.             begin
  3053.             alter table sysmergearticles add gen_cur int null
  3054.             if @@ERROR <> 0
  3055.                 return 1
  3056.             end
  3057.         if not exists (select * from syscolumns where id = object_id('sysmergearticles') and
  3058.                             name = 'before_image_objid')
  3059.             begin
  3060.             alter table sysmergearticles add before_image_objid    int    NULL
  3061.             if @@ERROR <> 0
  3062.                 return 1
  3063.             end
  3064.         if not exists (select * from syscolumns where id = object_id('sysmergearticles') and
  3065.                             name = 'before_view_objid')
  3066.             begin
  3067.             alter table sysmergearticles add before_view_objid    int    NULL
  3068.             if @@ERROR <> 0
  3069.                 return 1
  3070.             end
  3071.         end
  3072.     --  MSmerge_contents    
  3073.     SELECT @table_name = N'MSmerge_contents'
  3074.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_contents' )
  3075.     BEGIN
  3076.         IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc3MSmerge_contents' AND
  3077.         id = OBJECT_ID('MSmerge_contents') )
  3078.                 create index nc3MSmerge_contents on MSmerge_contents(tablenick, partchangegen)
  3079.                 
  3080.         IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc4MSmerge_contents' AND
  3081.         id = OBJECT_ID('MSmerge_contents') )
  3082.                 create index nc4MSmerge_contents on MSmerge_contents(generation, partchangegen) 
  3083.     END
  3084.  
  3085.     --    sysmergepublications
  3086.     SELECT @table_name = N'sysmergepublications'
  3087.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergepublications' )
  3088.     BEGIN 
  3089.         if not exists (select * from syscolumns where id = object_id('sysmergepublications')
  3090.             and name = 'keep_before_values')
  3091.         begin
  3092.         alter table sysmergepublications add keep_before_values int null
  3093.         if @@ERROR <> 0
  3094.             return 1
  3095.         end
  3096.  
  3097.         IF EXISTS ( SELECT pubid
  3098.             FROM sysmergepublications
  3099.             GROUP BY pubid
  3100.             HAVING COUNT(*) > 1 )
  3101.             RAISERROR (21144, 10, 4, @table_name)
  3102.         ELSE    
  3103.             IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1sysmergepublications' AND
  3104.                 id = OBJECT_ID('sysmergepublications') )
  3105.             CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergepublications
  3106.                 ON sysmergepublications(pubid)
  3107.     END
  3108.  
  3109.     --    MSmerge_genhistory    
  3110.     SELECT @table_name = N'MSmerge_genhistory'
  3111.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_genhistory' )
  3112.     BEGIN
  3113.     -- Only create the index index if guidsrc values are unique. Before SP1 it was possible
  3114.     -- for this table to contain dup guidsrc. This happened when the genhistory table was empty to start 
  3115.     -- and we insert an initial row (for no article) and then try to insert a row for the first 
  3116.     -- article without generating a new guid.  
  3117.     
  3118.         IF EXISTS ( SELECT guidsrc, pubid 
  3119.             FROM MSmerge_genhistory 
  3120.             GROUP BY guidsrc, pubid 
  3121.             HAVING COUNT(*) > 1 )
  3122.             RAISERROR (21144, 10, 5, @table_name)
  3123.         ELSE            
  3124.             IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc3MSmerge_genhistory' AND
  3125.                 id = OBJECT_ID('MSmerge_genhistory') )
  3126.             CREATE UNIQUE NONCLUSTERED INDEX nc3MSmerge_genhistory ON MSmerge_genhistory(guidsrc, pubid)        
  3127.             
  3128.             IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc4MSmerge_genhistory' AND
  3129.                 id = OBJECT_ID('MSmerge_genhistory') )
  3130.             create  index nc4MSmerge_genhistory on MSmerge_genhistory(coldate) 
  3131.             
  3132.     END
  3133.     
  3134.  
  3135.     --    MSmerge_delete_conflicts
  3136.     SELECT @table_name = N'MSmerge_delete_conflicts'
  3137.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_delete_conflicts' )
  3138.     BEGIN
  3139.         IF EXISTS ( SELECT tablenick, rowguid, origin_datasource
  3140.             FROM MSmerge_delete_conflicts
  3141.             GROUP BY tablenick, rowguid, origin_datasource
  3142.             HAVING COUNT(*) > 1 )
  3143.             RAISERROR (21144, 10, 6, @table_name)
  3144.         ELSE    
  3145.             IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1MSmerge_delete_conflicts' AND
  3146.                 id = OBJECT_ID('MSmerge_delete_conflicts') )
  3147.                 CREATE UNIQUE NONCLUSTERED INDEX nc1MSmerge_delete_conflicts 
  3148.                     ON MSmerge_delete_conflicts(tablenick, rowguid, origin_datasource)
  3149.     END
  3150.     
  3151.     --    sysmergeschemachange
  3152.     SELECT @table_name = N'sysmergeschemachange'
  3153.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergeschemachange' )
  3154.     BEGIN
  3155.         IF EXISTS ( SELECT schemaversion, pubid
  3156.             FROM sysmergeschemachange
  3157.             GROUP BY schemaversion, pubid
  3158.             HAVING COUNT(*) > 1 )
  3159.             RAISERROR (21144, 10, 7, @table_name)
  3160.         ELSE    
  3161.             BEGIN
  3162.                 IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'schemachangeversion' AND
  3163.                     id = OBJECT_ID('sysmergeschemachange') )            
  3164.                     DROP INDEX sysmergeschemachange.schemachangeversion
  3165.             
  3166.                 -- Recreate this index as unique clustered with one more field in index key.
  3167.                 CREATE UNIQUE CLUSTERED INDEX schemachangeversion ON sysmergeschemachange(schemaversion, pubid) 
  3168.             END
  3169.     END
  3170.     
  3171.  
  3172.     --    sysmergesubsetfilters    
  3173.     SELECT @table_name = N'sysmergesubsetfilters'
  3174.     IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergesubsetfilters' )
  3175.     BEGIN
  3176.         IF EXISTS ( SELECT join_filterid
  3177.             FROM sysmergesubsetfilters
  3178.             GROUP BY join_filterid
  3179.             HAVING COUNT(*) > 1 )
  3180.             RAISERROR (21144, 10, 8, @table_name)
  3181.         ELSE    
  3182.             IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1sysmergesubsetfilters' AND
  3183.                 id = OBJECT_ID('sysmergesubsetfilters') )
  3184.             CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergesubsetfilters ON sysmergesubsetfilters(join_filterid, pubid)
  3185.     END    
  3186.  
  3187.  
  3188.     /*
  3189.      * Views, procs and triggers supporting merge articles need regenerated with new 
  3190.      * DDL to take advantage of some fixes. If sysmergearticles, assume a merge pub or sub db
  3191.     */
  3192.     if (exists (select * from sysobjects where name = 'sysmergearticles'))
  3193.     begin
  3194.  
  3195.         declare @artnick        int
  3196.         declare @source_owner    sysname
  3197.         declare @source_object    sysname
  3198.         declare @qualified_name nvarchar(257)
  3199.         declare @artid            uniqueidentifier
  3200.         declare @pubid            uniqueidentifier
  3201.         declare @objid            int
  3202.         declare @pubname        sysname
  3203.         declare @article        sysname
  3204.         declare @snapshot_ready    int
  3205.         declare @retcode        integer
  3206.  
  3207.         -- only process those articles that have had a snapshot generated already
  3208.         select @artnick = min(a.nickname) from sysmergearticles a inner join sysmergepublications p on p.pubid = a.pubid where p.snapshot_ready =1
  3209.         while @artnick is not null
  3210.         begin
  3211.             -- find base table to compute number of columns
  3212.             select @objid = objid from sysmergearticles where nickname = @artnick
  3213.  
  3214.             -- regenerate the triggers
  3215.             select @source_owner = user_name(uid), @source_object = name from sysobjects where id = @objid
  3216.             select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object)
  3217.             exec dbo.sp_MSaddmergetriggers @qualified_name
  3218.  
  3219.             /* Loop through all articles that this table is involved in and regenerate the article procs */
  3220.             declare hcArtCursor CURSOR LOCAL FAST_FORWARD FOR select artid, pubid from sysmergearticles where nickname = @artnick order by artid, pubid
  3221.             
  3222.             OPEN hcArtCursor
  3223.             FETCH hcArtCursor INTO @artid, @pubid
  3224.             WHILE (@@fetch_status <> -1)
  3225.             BEGIN
  3226.                 select @pubname = name, @snapshot_ready = snapshot_ready from sysmergepublications where pubid = @pubid
  3227.                 -- regenerate procs, triggersonly for articles with snapshot ready
  3228.                 if @snapshot_ready>0
  3229.                 begin
  3230.                     select @article = name from sysmergearticles where artid = @artid and pubid = @pubid
  3231.                     exec @retcode = dbo.sp_MSsetartprocs @publication = @pubname,   @article = @article, @force_flag = 1
  3232.                     if @@ERROR <>0 OR @retcode <>0 
  3233.                         return (1)
  3234.                 END
  3235.                 FETCH hcArtCursor INTO @artid, @pubid
  3236.             END                         
  3237.             CLOSE hcArtCursor
  3238.             DEALLOCATE hcArtCursor
  3239.  
  3240.             -- find next article
  3241.             select @artnick = min(a.nickname) from sysmergearticles a inner join sysmergepublications p on p.pubid = a.pubid where p.snapshot_ready > 0 and a.nickname > @artnick
  3242.         end -- end article proc and trigger re-gen
  3243.  
  3244.         -- Loop over publications and recreate the views, skipping publications where snapshot is not ready
  3245.         select @pubname = min(name) from sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() and snapshot_ready > 0
  3246.         while @pubname is not null
  3247.         begin
  3248.             -- remake the publication views
  3249.             exec dbo.sp_MSpublicationview @pubname, 1
  3250.             select @pubname = min(name) from sysmergepublications where name > @pubname and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() and snapshot_ready > 0
  3251.  
  3252.         end
  3253.     end
  3254. GO
  3255. exec dbo.sp_MS_marksystemobject sp_vupgrade_mergetables
  3256. go
  3257.  
  3258. --------------------------------------------------------------------------------
  3259. -- END OF FILE: Turn off marking of system objects.
  3260. --    DO NOT ADD ANYTHING AFTER THIS POINT
  3261. --------------------------------------------------------------------------------
  3262. exec sp_MS_upd_sysobj_category 2
  3263. go
  3264.  
  3265. exec sp_configure 'allow updates',0
  3266. go
  3267.  
  3268. reconfigure with override
  3269. go
  3270.  
  3271.  
  3272.